]> git.sur5r.net Git - u-boot/blob - arch/x86/cpu/ivybridge/cpu.c
x86: Split up arch_cpu_init()
[u-boot] / arch / x86 / cpu / ivybridge / cpu.c
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 <errno.h>
16 #include <fdtdec.h>
17 #include <asm/cpu.h>
18 #include <asm/io.h>
19 #include <asm/lapic.h>
20 #include <asm/msr.h>
21 #include <asm/mtrr.h>
22 #include <asm/pci.h>
23 #include <asm/post.h>
24 #include <asm/processor.h>
25 #include <asm/arch/model_206ax.h>
26 #include <asm/arch/microcode.h>
27 #include <asm/arch/pch.h>
28 #include <asm/arch/sandybridge.h>
29
30 DECLARE_GLOBAL_DATA_PTR;
31
32 static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev)
33 {
34         /* Enable port 80 POST on LPC */
35         pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
36         clrbits_le32(RCB_REG(GCS), 4);
37 }
38
39 /*
40  * Enable Prefetching and Caching.
41  */
42 static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
43 {
44         u8 reg8;
45
46         pci_hose_read_config_byte(hose, dev, 0xdc, &reg8);
47         reg8 &= ~(3 << 2);
48         reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
49         pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
50 }
51
52 static int set_flex_ratio_to_tdp_nominal(void)
53 {
54         msr_t flex_ratio, msr;
55         u8 nominal_ratio;
56
57         /* Minimum CPU revision for configurable TDP support */
58         if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
59                 return -EINVAL;
60
61         /* Check for Flex Ratio support */
62         flex_ratio = msr_read(MSR_FLEX_RATIO);
63         if (!(flex_ratio.lo & FLEX_RATIO_EN))
64                 return -EINVAL;
65
66         /* Check for >0 configurable TDPs */
67         msr = msr_read(MSR_PLATFORM_INFO);
68         if (((msr.hi >> 1) & 3) == 0)
69                 return -EINVAL;
70
71         /* Use nominal TDP ratio for flex ratio */
72         msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
73         nominal_ratio = msr.lo & 0xff;
74
75         /* See if flex ratio is already set to nominal TDP ratio */
76         if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
77                 return 0;
78
79         /* Set flex ratio to nominal TDP ratio */
80         flex_ratio.lo &= ~0xff00;
81         flex_ratio.lo |= nominal_ratio << 8;
82         flex_ratio.lo |= FLEX_RATIO_LOCK;
83         msr_write(MSR_FLEX_RATIO, flex_ratio);
84
85         /* Set flex ratio in soft reset data register bits 11:6 */
86         clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
87                         (nominal_ratio & 0x3f) << 6);
88
89         /* Set soft reset control to use register value */
90         setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
91
92         /* Issue warm reset, will be "CPU only" due to soft reset data */
93         outb(0x0, PORT_RESET);
94         outb(0x6, PORT_RESET);
95         cpu_hlt();
96
97         /* Not reached */
98         return -EINVAL;
99 }
100
101 static void set_spi_speed(void)
102 {
103         u32 fdod;
104
105         /* Observe SPI Descriptor Component Section 0 */
106         writel(0x1000, RCB_REG(SPI_DESC_COMP0));
107
108         /* Extract the1 Write/Erase SPI Frequency from descriptor */
109         fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
110         fdod >>= 24;
111         fdod &= 7;
112
113         /* Set Software Sequence frequency to match */
114         clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
115 }
116
117 int arch_cpu_init(void)
118 {
119         post_code(POST_CPU_INIT);
120         timer_set_base(rdtsc());
121
122         return x86_cpu_init_f();
123 }
124
125 int arch_cpu_init_dm(void)
126 {
127         const void *blob = gd->fdt_blob;
128         struct pci_controller *hose;
129         int node;
130         int ret;
131
132         post_code(POST_CPU_INIT);
133         timer_set_base(rdtsc());
134
135         ret = x86_cpu_init_f();
136         if (ret)
137                 return ret;
138
139         ret = pci_early_init_hose(&hose);
140         if (ret)
141                 return ret;
142
143         node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC);
144         if (node < 0)
145                 return -ENOENT;
146         ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV);
147         if (ret)
148                 return ret;
149
150         enable_spi_prefetch(hose, PCH_LPC_DEV);
151
152         /* This is already done in start.S, but let's do it in C */
153         enable_port80_on_lpc(hose, PCH_LPC_DEV);
154
155         set_spi_speed();
156
157         /*
158          * We should do as little as possible before the serial console is
159          * up. Perhaps this should move to later. Our next lot of init
160          * happens in print_cpuinfo() when we have a console
161          */
162         ret = set_flex_ratio_to_tdp_nominal();
163         if (ret)
164                 return ret;
165
166         return 0;
167 }
168
169 static int enable_smbus(void)
170 {
171         pci_dev_t dev;
172         uint16_t value;
173
174         /* Set the SMBus device statically. */
175         dev = PCI_BDF(0x0, 0x1f, 0x3);
176
177         /* Check to make sure we've got the right device. */
178         value = x86_pci_read_config16(dev, 0x0);
179         if (value != 0x8086) {
180                 printf("SMBus controller not found\n");
181                 return -ENOSYS;
182         }
183
184         /* Set SMBus I/O base. */
185         x86_pci_write_config32(dev, SMB_BASE,
186                                SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
187
188         /* Set SMBus enable. */
189         x86_pci_write_config8(dev, HOSTC, HST_EN);
190
191         /* Set SMBus I/O space enable. */
192         x86_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
193
194         /* Disable interrupt generation. */
195         outb(0, SMBUS_IO_BASE + SMBHSTCTL);
196
197         /* Clear any lingering errors, so transactions can run. */
198         outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
199         debug("SMBus controller enabled\n");
200
201         return 0;
202 }
203
204 #define PCH_EHCI0_TEMP_BAR0 0xe8000000
205 #define PCH_EHCI1_TEMP_BAR0 0xe8000400
206 #define PCH_XHCI_TEMP_BAR0  0xe8001000
207
208 /*
209  * Setup USB controller MMIO BAR to prevent the reference code from
210  * resetting the controller.
211  *
212  * The BAR will be re-assigned during device enumeration so these are only
213  * temporary.
214  *
215  * This is used to speed up the resume path.
216  */
217 static void enable_usb_bar(void)
218 {
219         pci_dev_t usb0 = PCH_EHCI1_DEV;
220         pci_dev_t usb1 = PCH_EHCI2_DEV;
221         pci_dev_t usb3 = PCH_XHCI_DEV;
222         u32 cmd;
223
224         /* USB Controller 1 */
225         x86_pci_write_config32(usb0, PCI_BASE_ADDRESS_0,
226                                PCH_EHCI0_TEMP_BAR0);
227         cmd = x86_pci_read_config32(usb0, PCI_COMMAND);
228         cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
229         x86_pci_write_config32(usb0, PCI_COMMAND, cmd);
230
231         /* USB Controller 1 */
232         x86_pci_write_config32(usb1, PCI_BASE_ADDRESS_0,
233                                PCH_EHCI1_TEMP_BAR0);
234         cmd = x86_pci_read_config32(usb1, PCI_COMMAND);
235         cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
236         x86_pci_write_config32(usb1, PCI_COMMAND, cmd);
237
238         /* USB3 Controller */
239         x86_pci_write_config32(usb3, PCI_BASE_ADDRESS_0,
240                                PCH_XHCI_TEMP_BAR0);
241         cmd = x86_pci_read_config32(usb3, PCI_COMMAND);
242         cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
243         x86_pci_write_config32(usb3, PCI_COMMAND, cmd);
244 }
245
246 static int report_bist_failure(void)
247 {
248         if (gd->arch.bist != 0) {
249                 post_code(POST_BIST_FAILURE);
250                 printf("BIST failed: %08x\n", gd->arch.bist);
251                 return -EFAULT;
252         }
253
254         return 0;
255 }
256
257 int print_cpuinfo(void)
258 {
259         enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
260         char processor_name[CPU_MAX_NAME_LEN];
261         const char *name;
262         uint32_t pm1_cnt;
263         uint16_t pm1_sts;
264         int ret;
265
266         /* Halt if there was a built in self test failure */
267         ret = report_bist_failure();
268         if (ret)
269                 return ret;
270
271         enable_lapic();
272
273         ret = microcode_update_intel();
274         if (ret)
275                 return ret;
276
277         /* Enable upper 128bytes of CMOS */
278         writel(1 << 2, RCB_REG(RC));
279
280         /* TODO: cmos_post_init() */
281         if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
282                 debug("soft reset detected\n");
283                 boot_mode = PEI_BOOT_SOFT_RESET;
284
285                 /* System is not happy after keyboard reset... */
286                 debug("Issuing CF9 warm reset\n");
287                 outb(0x6, 0xcf9);
288                 cpu_hlt();
289         }
290
291         /* Early chipset init required before RAM init can work */
292         sandybridge_early_init(SANDYBRIDGE_MOBILE);
293
294         /* Check PM1_STS[15] to see if we are waking from Sx */
295         pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
296
297         /* Read PM1_CNT[12:10] to determine which Sx state */
298         pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
299
300         if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
301 #if CONFIG_HAVE_ACPI_RESUME
302                 debug("Resume from S3 detected.\n");
303                 boot_mode = PEI_BOOT_RESUME;
304                 /* Clear SLP_TYPE. This will break stage2 but
305                  * we care for that when we get there.
306                  */
307                 outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT);
308 #else
309                 debug("Resume from S3 detected, but disabled.\n");
310 #endif
311         } else {
312                 /*
313                  * TODO: An indication of life might be possible here (e.g.
314                  * keyboard light)
315                  */
316         }
317         post_code(POST_EARLY_INIT);
318
319         /* Enable SPD ROMs and DDR-III DRAM */
320         ret = enable_smbus();
321         if (ret)
322                 return ret;
323
324         /* Prepare USB controller early in S3 resume */
325         if (boot_mode == PEI_BOOT_RESUME)
326                 enable_usb_bar();
327
328         gd->arch.pei_boot_mode = boot_mode;
329
330         /* TODO: Move this to the board or driver */
331         x86_pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
332         x86_pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10);
333
334         /* Print processor name */
335         name = cpu_get_name(processor_name);
336         printf("CPU:   %s\n", name);
337
338         post_code(POST_CPU_INFO);
339
340         return 0;
341 }