xref: /rk3399_rockchip-uboot/arch/x86/cpu/ivybridge/cpu.c (revision 06d336cca284cc767a095ce40afca79b4aa0ecb0)
1 /*
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  * and src/cpu/intel/model_206ax/bootblock.c
8  * 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>
15 #include <dm.h>
16 #include <errno.h>
17 #include <fdtdec.h>
18 #include <pch.h>
19 #include <asm/cpu.h>
20 #include <asm/intel_regs.h>
21 #include <asm/io.h>
22 #include <asm/lapic.h>
23 #include <asm/microcode.h>
24 #include <asm/msr.h>
25 #include <asm/mtrr.h>
26 #include <asm/pci.h>
27 #include <asm/post.h>
28 #include <asm/processor.h>
29 #include <asm/arch/model_206ax.h>
30 #include <asm/arch/pch.h>
31 #include <asm/arch/sandybridge.h>
32 
33 DECLARE_GLOBAL_DATA_PTR;
34 
35 static int set_flex_ratio_to_tdp_nominal(void)
36 {
37 	msr_t flex_ratio, msr;
38 	u8 nominal_ratio;
39 
40 	/* Minimum CPU revision for configurable TDP support */
41 	if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
42 		return -EINVAL;
43 
44 	/* Check for Flex Ratio support */
45 	flex_ratio = msr_read(MSR_FLEX_RATIO);
46 	if (!(flex_ratio.lo & FLEX_RATIO_EN))
47 		return -EINVAL;
48 
49 	/* Check for >0 configurable TDPs */
50 	msr = msr_read(MSR_PLATFORM_INFO);
51 	if (((msr.hi >> 1) & 3) == 0)
52 		return -EINVAL;
53 
54 	/* Use nominal TDP ratio for flex ratio */
55 	msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
56 	nominal_ratio = msr.lo & 0xff;
57 
58 	/* See if flex ratio is already set to nominal TDP ratio */
59 	if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
60 		return 0;
61 
62 	/* Set flex ratio to nominal TDP ratio */
63 	flex_ratio.lo &= ~0xff00;
64 	flex_ratio.lo |= nominal_ratio << 8;
65 	flex_ratio.lo |= FLEX_RATIO_LOCK;
66 	msr_write(MSR_FLEX_RATIO, flex_ratio);
67 
68 	/* Set flex ratio in soft reset data register bits 11:6 */
69 	clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
70 			(nominal_ratio & 0x3f) << 6);
71 
72 	/* Set soft reset control to use register value */
73 	setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
74 
75 	/* Issue warm reset, will be "CPU only" due to soft reset data */
76 	outb(0x0, PORT_RESET);
77 	outb(SYS_RST | RST_CPU, PORT_RESET);
78 	cpu_hlt();
79 
80 	/* Not reached */
81 	return -EINVAL;
82 }
83 
84 int arch_cpu_init(void)
85 {
86 	post_code(POST_CPU_INIT);
87 
88 	return x86_cpu_init_f();
89 }
90 
91 int arch_cpu_init_dm(void)
92 {
93 	struct pci_controller *hose;
94 	struct udevice *bus, *dev;
95 	int ret;
96 
97 	post_code(0x70);
98 	ret = uclass_get_device(UCLASS_PCI, 0, &bus);
99 	post_code(0x71);
100 	if (ret)
101 		return ret;
102 	post_code(0x72);
103 	hose = dev_get_uclass_priv(bus);
104 
105 	/* TODO(sjg@chromium.org): Get rid of gd->hose */
106 	gd->hose = hose;
107 
108 	ret = uclass_first_device_err(UCLASS_LPC, &dev);
109 	if (ret)
110 		return ret;
111 
112 	/*
113 	 * We should do as little as possible before the serial console is
114 	 * up. Perhaps this should move to later. Our next lot of init
115 	 * happens in print_cpuinfo() when we have a console
116 	 */
117 	ret = set_flex_ratio_to_tdp_nominal();
118 	if (ret)
119 		return ret;
120 
121 	return 0;
122 }
123 
124 #define PCH_EHCI0_TEMP_BAR0 0xe8000000
125 #define PCH_EHCI1_TEMP_BAR0 0xe8000400
126 #define PCH_XHCI_TEMP_BAR0  0xe8001000
127 
128 /*
129  * Setup USB controller MMIO BAR to prevent the reference code from
130  * resetting the controller.
131  *
132  * The BAR will be re-assigned during device enumeration so these are only
133  * temporary.
134  *
135  * This is used to speed up the resume path.
136  */
137 static void enable_usb_bar(struct udevice *bus)
138 {
139 	pci_dev_t usb0 = PCH_EHCI1_DEV;
140 	pci_dev_t usb1 = PCH_EHCI2_DEV;
141 	pci_dev_t usb3 = PCH_XHCI_DEV;
142 	ulong cmd;
143 
144 	/* USB Controller 1 */
145 	pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0,
146 			     PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32);
147 	pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32);
148 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
149 	pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32);
150 
151 	/* USB Controller 2 */
152 	pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0,
153 			     PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32);
154 	pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32);
155 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
156 	pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32);
157 
158 	/* USB3 Controller 1 */
159 	pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0,
160 			     PCH_XHCI_TEMP_BAR0, PCI_SIZE_32);
161 	pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32);
162 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
163 	pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
164 }
165 
166 static int report_bist_failure(void)
167 {
168 	if (gd->arch.bist != 0) {
169 		post_code(POST_BIST_FAILURE);
170 		printf("BIST failed: %08x\n", gd->arch.bist);
171 		return -EFAULT;
172 	}
173 
174 	return 0;
175 }
176 
177 int print_cpuinfo(void)
178 {
179 	enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
180 	char processor_name[CPU_MAX_NAME_LEN];
181 	struct udevice *dev, *lpc;
182 	const char *name;
183 	uint32_t pm1_cnt;
184 	uint16_t pm1_sts;
185 	int ret;
186 
187 	/* Halt if there was a built in self test failure */
188 	ret = report_bist_failure();
189 	if (ret)
190 		return ret;
191 
192 	enable_lapic();
193 
194 	ret = microcode_update_intel();
195 	if (ret)
196 		return ret;
197 
198 	/* Enable upper 128bytes of CMOS */
199 	writel(1 << 2, RCB_REG(RC));
200 
201 	/* TODO: cmos_post_init() */
202 	if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
203 		debug("soft reset detected\n");
204 		boot_mode = PEI_BOOT_SOFT_RESET;
205 
206 		/* System is not happy after keyboard reset... */
207 		debug("Issuing CF9 warm reset\n");
208 		reset_cpu(0);
209 	}
210 
211 	/* Early chipset init required before RAM init can work */
212 	uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
213 
214 	ret = uclass_first_device_err(UCLASS_LPC, &lpc);
215 	if (ret)
216 		return ret;
217 
218 	/* Cause the SATA device to do its early init */
219 	uclass_first_device(UCLASS_DISK, &dev);
220 
221 	/* Check PM1_STS[15] to see if we are waking from Sx */
222 	pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
223 
224 	/* Read PM1_CNT[12:10] to determine which Sx state */
225 	pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
226 
227 	if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
228 		debug("Resume from S3 detected, but disabled.\n");
229 	} else {
230 		/*
231 		 * TODO: An indication of life might be possible here (e.g.
232 		 * keyboard light)
233 		 */
234 	}
235 	post_code(POST_EARLY_INIT);
236 
237 	/* Enable SPD ROMs and DDR-III DRAM */
238 	ret = uclass_first_device_err(UCLASS_I2C, &dev);
239 	if (ret)
240 		return ret;
241 
242 	/* Prepare USB controller early in S3 resume */
243 	if (boot_mode == PEI_BOOT_RESUME)
244 		enable_usb_bar(pci_get_controller(lpc->parent));
245 
246 	gd->arch.pei_boot_mode = boot_mode;
247 
248 	/* Print processor name */
249 	name = cpu_get_name(processor_name);
250 	printf("CPU:   %s\n", name);
251 
252 	post_code(POST_CPU_INFO);
253 
254 	return 0;
255 }
256 
257 void board_debug_uart_init(void)
258 {
259 	/* This enables the debug UART */
260 	pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN,
261 			     PCI_SIZE_16);
262 }
263