blob: 155c8a2e46de8797b009155a036edf8d49afb6b0 [file] [log] [blame]
Lee Leahy77ff0b12015-05-05 15:07:29 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
Lee Leahy32471722015-04-20 15:20:28 -07005 * Copyright (C) 2015 Intel Corp.
Lee Leahy77ff0b12015-05-05 15:07:29 -07006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Lee Leahy77ff0b12015-05-05 15:07:29 -070015 */
16
17#include <arch/cpu.h>
18#include <arch/acpi.h>
Lee Leahy32471722015-04-20 15:20:28 -070019#include <bootstate.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070020#include <cbmem.h>
21#include <console/console.h>
22#include <cpu/intel/microcode.h>
23#include <cpu/x86/cr.h>
24#include <cpu/x86/msr.h>
25#include <device/device.h>
26#include <device/pci_def.h>
27#include <device/pci_ops.h>
Aaron Durbin789f2b62015-09-09 17:05:06 -050028#include <fsp/util.h>
Lee Leahy32471722015-04-20 15:20:28 -070029#include <romstage_handoff.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070030#include <soc/gpio.h>
31#include <soc/lpc.h>
32#include <soc/msr.h>
33#include <soc/nvs.h>
34#include <soc/pattrs.h>
35#include <soc/pci_devs.h>
Lee Leahy32471722015-04-20 15:20:28 -070036#include <soc/pm.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070037#include <soc/ramstage.h>
Duncan Lauriee73da802015-09-08 16:16:34 -070038#include <soc/intel/common/acpi.h>
Lee Leahy32471722015-04-20 15:20:28 -070039#include <boardid.h>
40#include <stdlib.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070041
42#define SHOW_PATTRS 1
43
Lee Leahy32471722015-04-20 15:20:28 -070044struct pattrs __global_pattrs;
45
Lee Leahy77ff0b12015-05-05 15:07:29 -070046static void detect_num_cpus(struct pattrs *attrs)
47{
48 int ecx = 0;
49
50 while (1) {
51 struct cpuid_result leaf_b;
52
53 leaf_b = cpuid_ext(0xb, ecx);
54
Lee Leahy32471722015-04-20 15:20:28 -070055 /*
56 * The SOC doesn't have hyperthreading so just determine the
57 * number of cores by from level type (ecx[15:8] == * 2).
58 */
Lee Leahy77ff0b12015-05-05 15:07:29 -070059 if ((leaf_b.ecx & 0xff00) == 0x0200) {
60 attrs->num_cpus = leaf_b.ebx & 0xffff;
61 break;
62 }
63 ecx++;
64 }
65}
66
67static inline void fill_in_msr(msr_t *msr, int idx)
68{
69 *msr = rdmsr(idx);
70 if (SHOW_PATTRS) {
71 printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n",
72 idx, msr->hi, msr->lo);
73 }
74}
75
Lee Leahy32471722015-04-20 15:20:28 -070076static const char * const stepping_str[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -070077 "A0", "A1", "B0", "B1", "B2", "B3", "C0"
78};
79
80static void fill_in_pattrs(void)
81{
82 device_t dev;
83 msr_t msr;
84 struct pattrs *attrs = (struct pattrs *)pattrs_get();
85
86 attrs->cpuid = cpuid_eax(1);
87 dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
88 attrs->revid = pci_read_config8(dev, REVID);
89 /* The revision to stepping IDs have two values per metal stepping. */
90 if (attrs->revid >= RID_C_STEPPING_START) {
91 attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2;
92 attrs->stepping += STEP_C0;
93 } else if (attrs->revid >= RID_B_STEPPING_START) {
94 attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2;
95 attrs->stepping += STEP_B0;
96 } else {
97 attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2;
98 attrs->stepping += STEP_A0;
99 }
100
101 attrs->microcode_patch = intel_microcode_find();
102 attrs->address_bits = cpuid_eax(0x80000008) & 0xff;
103 detect_num_cpus(attrs);
104
105 if (SHOW_PATTRS) {
Lee Leahy32471722015-04-20 15:20:28 -0700106 printk(BIOS_DEBUG, "Cpuid %08x cpus %d rid %02x step %s\n",
Lee Leahy77ff0b12015-05-05 15:07:29 -0700107 attrs->cpuid, attrs->num_cpus, attrs->revid,
108 (attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" :
109 stepping_str[attrs->stepping]);
110 }
111
112 fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID);
113 fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO);
114
115 /* Set IA core speed ratio and voltages */
Lee Leahy32471722015-04-20 15:20:28 -0700116 fill_in_msr(&msr, MSR_IACORE_RATIOS);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700117 attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f;
118 attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
119 attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
Lee Leahy32471722015-04-20 15:20:28 -0700120 fill_in_msr(&msr, MSR_IACORE_TURBO_RATIOS);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700121 attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
122
Lee Leahy32471722015-04-20 15:20:28 -0700123 fill_in_msr(&msr, MSR_IACORE_VIDS);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700124 attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f;
125 attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
126 attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
Lee Leahy32471722015-04-20 15:20:28 -0700127 fill_in_msr(&msr, MSR_IACORE_TURBO_VIDS);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700128 attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
129
130 /* Set bus clock speed */
Subrata Banik45a221d2015-08-05 17:01:55 +0530131 attrs->bclk_khz = cpu_bus_freq_khz();
Lee Leahy32471722015-04-20 15:20:28 -0700132}
133
134static inline void set_acpi_sleep_type(int val)
135{
136#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
137 acpi_slp_type = val;
138#endif
Lee Leahy77ff0b12015-05-05 15:07:29 -0700139}
140
Duncan Lauriee73da802015-09-08 16:16:34 -0700141/* Save wake source information for calculating ACPI _SWS values */
142int soc_fill_acpi_wake(uint32_t *pm1, uint32_t **gpe0)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700143{
144 struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
Duncan Lauriee73da802015-09-08 16:16:34 -0700145 static uint32_t gpe0_sts;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700146
Duncan Lauriee73da802015-09-08 16:16:34 -0700147 *pm1 = ps->pm1_sts & ps->pm1_en;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700148
Duncan Lauriee73da802015-09-08 16:16:34 -0700149 gpe0_sts = ps->gpe0_sts & ps->gpe0_en;
150 *gpe0 = &gpe0_sts;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700151
Duncan Lauriee73da802015-09-08 16:16:34 -0700152 return 1;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700153}
154
155static void s3_resume_prepare(void)
156{
157 global_nvs_t *gnvs;
Lee Leahy32471722015-04-20 15:20:28 -0700158 struct romstage_handoff *romstage_handoff;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700159
160 gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
Lee Leahy32471722015-04-20 15:20:28 -0700161
162 romstage_handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
163 if (romstage_handoff == NULL || romstage_handoff->s3_resume == 0) {
164 if (gnvs != NULL)
165 memset(gnvs, 0, sizeof(global_nvs_t));
166 set_acpi_sleep_type(0);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700167 return;
Lee Leahy32471722015-04-20 15:20:28 -0700168 }
Lee Leahy77ff0b12015-05-05 15:07:29 -0700169
Lee Leahy32471722015-04-20 15:20:28 -0700170 set_acpi_sleep_type(3);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700171}
172
Lee Leahy32471722015-04-20 15:20:28 -0700173static void set_board_id(void)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700174{
Lee Leahy32471722015-04-20 15:20:28 -0700175 global_nvs_t *gnvs;
176
177 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
178 if (!gnvs) {
179 printk(BIOS_ERR, "Unable to locate Global NVS\n");
180 return;
181 }
182 gnvs->bdid = board_id();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700183}
184
Lee Leahy32471722015-04-20 15:20:28 -0700185void soc_init_pre_device(struct soc_intel_braswell_config *config)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700186{
187 struct soc_gpio_config *gpio_config;
188
189 fill_in_pattrs();
190
Lee Leahy77ff0b12015-05-05 15:07:29 -0700191 /* Allow for SSE instructions to be executed. */
192 write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
193
194 /* Indicate S3 resume to rest of ramstage. */
195 s3_resume_prepare();
196
Lee Leahy32471722015-04-20 15:20:28 -0700197 /* Perform silicon specific init. */
198 intel_silicon_init();
Hannah Williamsb0eb5942015-08-23 17:24:43 -0700199 set_max_freq();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700200
Lee Leahy32471722015-04-20 15:20:28 -0700201 set_board_id();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700202 /* Get GPIO initial states from mainboard */
203 gpio_config = mainboard_get_gpios();
204 setup_soc_gpios(gpio_config, config->enable_xdp_tap);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700205}