Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 1 | /* |
| 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 Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 14 | */ |
| 15 | |
| 16 | #include <arch/cpu.h> |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 17 | #include <arch/acpi.h> |
| 18 | #include <cbmem.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 19 | #include <console/console.h> |
| 20 | #include <cpu/intel/microcode.h> |
Aaron Durbin | 1ce0b30 | 2013-10-10 12:47:47 -0500 | [diff] [blame] | 21 | #include <cpu/x86/cr.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 22 | #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älkki | 9e94dbf | 2015-01-08 20:03:18 +0200 | [diff] [blame] | 27 | #include <string.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 28 | |
Julius Werner | 18ea2d3 | 2014-10-07 16:42:17 -0700 | [diff] [blame] | 29 | #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 Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 37 | #include <soc/iosf.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 38 | |
| 39 | /* Global PATTRS */ |
| 40 | DEFINE_PATTRS; |
| 41 | |
| 42 | #define SHOW_PATTRS 1 |
| 43 | |
| 44 | static 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 | |
| 63 | static 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 Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 72 | static const char *stepping_str[] = { |
Ben Gardner | 2d3d1b7 | 2015-11-19 16:12:21 -0600 | [diff] [blame] | 73 | "A0", "A1", "B0", "B1", "B2", "B3", "C0", "D0", |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 74 | }; |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 75 | |
| 76 | static void fill_in_pattrs(void) |
| 77 | { |
| 78 | device_t dev; |
Duncan Laurie | 6aa9f1f | 2013-11-07 12:47:35 -0800 | [diff] [blame] | 79 | msr_t msr; |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 80 | 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 Gardner | 2d3d1b7 | 2015-11-19 16:12:21 -0600 | [diff] [blame] | 86 | 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 Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 90 | attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2; |
| 91 | attrs->stepping += STEP_C0; |
| 92 | } else if (attrs->revid >= RID_B_STEPPING_START) { |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 93 | 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 Laurie | 6aa9f1f | 2013-11-07 12:47:35 -0800 | [diff] [blame] | 113 | |
| 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 Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 131 | } |
| 132 | |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 133 | /* Save bit index for first enabled event in PM1_STS for \_SB._SWS */ |
| 134 | static 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 Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 159 | static void s3_resume_prepare(void) |
| 160 | { |
| 161 | global_nvs_t *gnvs; |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 162 | |
| 163 | gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t)); |
Kyösti Mälkki | 9e94dbf | 2015-01-08 20:03:18 +0200 | [diff] [blame] | 164 | if (gnvs == NULL) |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 165 | return; |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 166 | |
Kyösti Mälkki | 9e94dbf | 2015-01-08 20:03:18 +0200 | [diff] [blame] | 167 | if (!acpi_is_wakeup_s3()) |
| 168 | memset(gnvs, 0, sizeof(global_nvs_t)); |
| 169 | else |
| 170 | s3_save_acpi_wake_source(gnvs); |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 171 | } |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 172 | |
Kane Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 173 | static 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 Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 182 | void baytrail_init_pre_device(struct soc_intel_baytrail_config *config) |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 183 | { |
Kein Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 184 | struct soc_gpio_config *gpio_config; |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 185 | |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 186 | fill_in_pattrs(); |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 187 | |
Kane Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 188 | if (!config->disable_ddr_2x_refresh_rate) |
| 189 | baytrail_enable_2x_refresh_rate(); |
| 190 | |
Aaron Durbin | 1ce0b30 | 2013-10-10 12:47:47 -0500 | [diff] [blame] | 191 | /* Allow for SSE instructions to be executed. */ |
| 192 | write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT); |
| 193 | |
Aaron Durbin | 7d34c60 | 2013-12-12 10:07:00 -0800 | [diff] [blame] | 194 | /* Indicate S3 resume to rest of ramstage. */ |
| 195 | s3_resume_prepare(); |
| 196 | |
Aaron Durbin | ae5d83e | 2013-10-24 10:21:43 -0500 | [diff] [blame] | 197 | /* Run reference code. */ |
| 198 | baytrail_run_reference_code(); |
| 199 | |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 200 | /* Get GPIO initial states from mainboard */ |
Kein Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 201 | gpio_config = mainboard_get_gpios(); |
| 202 | setup_soc_gpios(gpio_config, config->enable_xdp_tap); |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 203 | |
Aaron Durbin | c626b74 | 2013-11-12 16:40:33 -0600 | [diff] [blame] | 204 | baytrail_init_scc(); |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 205 | } |