blob: c0cdd23a2bc32ca31c4357b11f78e38e9007aa0f [file] [log] [blame]
Aaron Durbin452d31a2013-09-24 16:47:49 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbin452d31a2013-09-24 16:47:49 -050014 */
15
16#include <arch/cpu.h>
Aaron Durbin6e77bee2013-10-30 15:25:42 -050017#include <arch/acpi.h>
18#include <cbmem.h>
Aaron Durbin452d31a2013-09-24 16:47:49 -050019#include <console/console.h>
20#include <cpu/intel/microcode.h>
Aaron Durbin1ce0b302013-10-10 12:47:47 -050021#include <cpu/x86/cr.h>
Aaron Durbin452d31a2013-09-24 16:47:49 -050022#include <cpu/x86/msr.h>
23#include <device/device.h>
24#include <device/pci_def.h>
25#include <device/pci_ops.h>
26#include <stdlib.h>
Kyösti Mälkki9e94dbf2015-01-08 20:03:18 +020027#include <string.h>
Aaron Durbin452d31a2013-09-24 16:47:49 -050028
Julius Werner18ea2d32014-10-07 16:42:17 -070029#include <soc/gpio.h>
30#include <soc/lpc.h>
31#include <soc/msr.h>
32#include <soc/nvs.h>
33#include <soc/pattrs.h>
34#include <soc/pci_devs.h>
35#include <soc/pmc.h>
36#include <soc/ramstage.h>
Kane Chenba9b7bf2015-01-17 08:19:54 +080037#include <soc/iosf.h>
Aaron Durbin452d31a2013-09-24 16:47:49 -050038
39/* Global PATTRS */
40DEFINE_PATTRS;
41
42#define SHOW_PATTRS 1
43
44static void detect_num_cpus(struct pattrs *attrs)
45{
46 int ecx = 0;
47
48 while (1) {
49 struct cpuid_result leaf_b;
50
51 leaf_b = cpuid_ext(0xb, ecx);
52
53 /* Bay Trail doesn't have hyperthreading so just determine the
54 * number of cores by from level type (ecx[15:8] == * 2). */
55 if ((leaf_b.ecx & 0xff00) == 0x0200) {
56 attrs->num_cpus = leaf_b.ebx & 0xffff;
57 break;
58 }
59 ecx++;
60 }
61}
62
63static inline void fill_in_msr(msr_t *msr, int idx)
64{
65 *msr = rdmsr(idx);
66 if (SHOW_PATTRS) {
67 printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n",
68 idx, msr->hi, msr->lo);
69 }
70}
71
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080072static const char *stepping_str[] = {
Ben Gardner2d3d1b72015-11-19 16:12:21 -060073 "A0", "A1", "B0", "B1", "B2", "B3", "C0", "D0",
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080074};
Aaron Durbin452d31a2013-09-24 16:47:49 -050075
76static void fill_in_pattrs(void)
77{
78 device_t dev;
Duncan Laurie6aa9f1f2013-11-07 12:47:35 -080079 msr_t msr;
Aaron Durbin452d31a2013-09-24 16:47:49 -050080 struct pattrs *attrs = (struct pattrs *)pattrs_get();
81
82 attrs->cpuid = cpuid_eax(1);
83 dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
84 attrs->revid = pci_read_config8(dev, REVID);
85 /* The revision to stepping IDs have two values per metal stepping. */
Ben Gardner2d3d1b72015-11-19 16:12:21 -060086 if (attrs->revid >= RID_D_STEPPING_START) {
87 attrs->stepping = (attrs->revid - RID_D_STEPPING_START) / 2;
88 attrs->stepping += STEP_D0;
89 } else if (attrs->revid >= RID_C_STEPPING_START) {
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080090 attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2;
91 attrs->stepping += STEP_C0;
92 } else if (attrs->revid >= RID_B_STEPPING_START) {
Aaron Durbin452d31a2013-09-24 16:47:49 -050093 attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2;
94 attrs->stepping += STEP_B0;
95 } else {
96 attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2;
97 attrs->stepping += STEP_A0;
98 }
99
100 attrs->microcode_patch = intel_microcode_find();
101 attrs->address_bits = cpuid_eax(0x80000008) & 0xff;
102 detect_num_cpus(attrs);
103
104 if (SHOW_PATTRS) {
105 printk(BIOS_DEBUG, "BYT: cpuid %08x cpus %d rid %02x step %s\n",
106 attrs->cpuid, attrs->num_cpus, attrs->revid,
107 (attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" :
108 stepping_str[attrs->stepping]);
109 }
110
111 fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID);
112 fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO);
Duncan Laurie6aa9f1f2013-11-07 12:47:35 -0800113
114 /* Set IA core speed ratio and voltages */
115 msr = rdmsr(MSR_IACORE_RATIOS);
116 attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f;
117 attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
118 attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
119 msr = rdmsr(MSR_IACORE_TURBO_RATIOS);
120 attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
121
122 msr = rdmsr(MSR_IACORE_VIDS);
123 attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f;
124 attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
125 attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
126 msr = rdmsr(MSR_IACORE_TURBO_VIDS);
127 attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
128
129 /* Set bus clock speed */
130 attrs->bclk_khz = bus_freq_khz();
Aaron Durbin452d31a2013-09-24 16:47:49 -0500131}
132
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800133/* Save bit index for first enabled event in PM1_STS for \_SB._SWS */
134static void s3_save_acpi_wake_source(global_nvs_t *gnvs)
135{
136 struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
137 uint16_t pm1;
138
139 if (!ps)
140 return;
141
142 pm1 = ps->pm1_sts & ps->pm1_en;
143
144 /* Scan for first set bit in PM1 */
145 for (gnvs->pm1i = 0; gnvs->pm1i < 16; gnvs->pm1i++) {
146 if (pm1 & 1)
147 break;
148 pm1 >>= 1;
149 }
150
151 /* If unable to determine then return -1 */
152 if (gnvs->pm1i >= 16)
153 gnvs->pm1i = -1;
154
155 printk(BIOS_DEBUG, "ACPI System Wake Source is PM1 Index %d\n",
156 gnvs->pm1i);
157}
158
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500159static void s3_resume_prepare(void)
160{
161 global_nvs_t *gnvs;
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500162
163 gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
Kyösti Mälkki9e94dbf2015-01-08 20:03:18 +0200164 if (gnvs == NULL)
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500165 return;
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500166
Kyösti Mälkki9e94dbf2015-01-08 20:03:18 +0200167 if (!acpi_is_wakeup_s3())
168 memset(gnvs, 0, sizeof(global_nvs_t));
169 else
170 s3_save_acpi_wake_source(gnvs);
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500171}
Shawn Nematbakhshebe3b3c2013-09-26 16:44:14 -0700172
Kane Chenba9b7bf2015-01-17 08:19:54 +0800173static void baytrail_enable_2x_refresh_rate(void)
174{
175 u32 reg;
176 reg = iosf_dunit_read(0x8);
177 reg = reg & ~0x7000;
178 reg = reg | 0x2000;
179 iosf_dunit_write(0x8, reg);
180}
181
Kein Yuan35110232014-02-22 12:26:55 -0800182void baytrail_init_pre_device(struct soc_intel_baytrail_config *config)
Aaron Durbin452d31a2013-09-24 16:47:49 -0500183{
Kein Yuan35110232014-02-22 12:26:55 -0800184 struct soc_gpio_config *gpio_config;
Shawn Nematbakhshebe3b3c2013-09-26 16:44:14 -0700185
Aaron Durbin452d31a2013-09-24 16:47:49 -0500186 fill_in_pattrs();
Shawn Nematbakhshebe3b3c2013-09-26 16:44:14 -0700187
Kane Chenba9b7bf2015-01-17 08:19:54 +0800188 if (!config->disable_ddr_2x_refresh_rate)
189 baytrail_enable_2x_refresh_rate();
190
Aaron Durbin1ce0b302013-10-10 12:47:47 -0500191 /* Allow for SSE instructions to be executed. */
192 write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
193
Aaron Durbin7d34c602013-12-12 10:07:00 -0800194 /* Indicate S3 resume to rest of ramstage. */
195 s3_resume_prepare();
196
Aaron Durbinae5d83e2013-10-24 10:21:43 -0500197 /* Run reference code. */
198 baytrail_run_reference_code();
199
Shawn Nematbakhshebe3b3c2013-09-26 16:44:14 -0700200 /* Get GPIO initial states from mainboard */
Kein Yuan35110232014-02-22 12:26:55 -0800201 gpio_config = mainboard_get_gpios();
202 setup_soc_gpios(gpio_config, config->enable_xdp_tap);
Aaron Durbin6e77bee2013-10-30 15:25:42 -0500203
Aaron Durbinc626b742013-11-12 16:40:33 -0600204 baytrail_init_scc();
Aaron Durbin452d31a2013-09-24 16:47:49 -0500205}