Angel Pons | c3f58f6 | 2020-04-05 15:46:41 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 2 | |
| 3 | #include <arch/cpu.h> |
Kyösti Mälkki | 3139c8d | 2020-06-28 16:33:33 +0300 | [diff] [blame] | 4 | #include <acpi/acpi_gnvs.h> |
Kyösti Mälkki | 2787237 | 2021-01-21 16:05:26 +0200 | [diff] [blame] | 5 | #include <acpi/acpi_pm.h> |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 6 | #include <bootstate.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 7 | #include <console/console.h> |
| 8 | #include <cpu/intel/microcode.h> |
Aaron Durbin | 1ce0b30 | 2013-10-10 12:47:47 -0500 | [diff] [blame] | 9 | #include <cpu/x86/cr.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 10 | #include <cpu/x86/msr.h> |
| 11 | #include <device/device.h> |
| 12 | #include <device/pci_def.h> |
| 13 | #include <device/pci_ops.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 14 | |
Kyösti Mälkki | 4bd9187 | 2021-03-16 19:02:26 +0200 | [diff] [blame] | 15 | #include <soc/device_nvs.h> |
Julius Werner | 18ea2d3 | 2014-10-07 16:42:17 -0700 | [diff] [blame] | 16 | #include <soc/gpio.h> |
| 17 | #include <soc/lpc.h> |
| 18 | #include <soc/msr.h> |
| 19 | #include <soc/nvs.h> |
| 20 | #include <soc/pattrs.h> |
| 21 | #include <soc/pci_devs.h> |
Angel Pons | b5320b2 | 2020-07-07 18:27:30 +0200 | [diff] [blame] | 22 | #include <soc/pm.h> |
Julius Werner | 18ea2d3 | 2014-10-07 16:42:17 -0700 | [diff] [blame] | 23 | #include <soc/ramstage.h> |
Kane Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 24 | #include <soc/iosf.h> |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 25 | |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 26 | #define SHOW_PATTRS 1 |
| 27 | |
Angel Pons | baebe2a | 2020-07-07 18:21:27 +0200 | [diff] [blame] | 28 | struct pattrs __global_pattrs; |
| 29 | |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 30 | static void detect_num_cpus(struct pattrs *attrs) |
| 31 | { |
| 32 | int ecx = 0; |
| 33 | |
| 34 | while (1) { |
| 35 | struct cpuid_result leaf_b; |
| 36 | |
| 37 | leaf_b = cpuid_ext(0xb, ecx); |
| 38 | |
| 39 | /* Bay Trail doesn't have hyperthreading so just determine the |
| 40 | * number of cores by from level type (ecx[15:8] == * 2). */ |
| 41 | if ((leaf_b.ecx & 0xff00) == 0x0200) { |
| 42 | attrs->num_cpus = leaf_b.ebx & 0xffff; |
| 43 | break; |
| 44 | } |
| 45 | ecx++; |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | static inline void fill_in_msr(msr_t *msr, int idx) |
| 50 | { |
| 51 | *msr = rdmsr(idx); |
| 52 | if (SHOW_PATTRS) { |
| 53 | printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n", |
| 54 | idx, msr->hi, msr->lo); |
| 55 | } |
| 56 | } |
| 57 | |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 58 | static const char *stepping_str[] = { |
Ben Gardner | 2d3d1b7 | 2015-11-19 16:12:21 -0600 | [diff] [blame] | 59 | "A0", "A1", "B0", "B1", "B2", "B3", "C0", "D0", |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 60 | }; |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 61 | |
| 62 | static void fill_in_pattrs(void) |
| 63 | { |
Elyes HAOUAS | 17a3ceb | 2018-05-22 10:42:28 +0200 | [diff] [blame] | 64 | struct device *dev; |
Duncan Laurie | 6aa9f1f | 2013-11-07 12:47:35 -0800 | [diff] [blame] | 65 | msr_t msr; |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 66 | struct pattrs *attrs = (struct pattrs *)pattrs_get(); |
| 67 | |
| 68 | attrs->cpuid = cpuid_eax(1); |
Kyösti Mälkki | c70eed1 | 2018-05-22 02:18:00 +0300 | [diff] [blame] | 69 | dev = pcidev_on_root(LPC_DEV, LPC_FUNC); |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 70 | attrs->revid = pci_read_config8(dev, REVID); |
| 71 | /* The revision to stepping IDs have two values per metal stepping. */ |
Ben Gardner | 2d3d1b7 | 2015-11-19 16:12:21 -0600 | [diff] [blame] | 72 | if (attrs->revid >= RID_D_STEPPING_START) { |
| 73 | attrs->stepping = (attrs->revid - RID_D_STEPPING_START) / 2; |
| 74 | attrs->stepping += STEP_D0; |
| 75 | } else if (attrs->revid >= RID_C_STEPPING_START) { |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 76 | attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2; |
| 77 | attrs->stepping += STEP_C0; |
| 78 | } else if (attrs->revid >= RID_B_STEPPING_START) { |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 79 | attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2; |
| 80 | attrs->stepping += STEP_B0; |
| 81 | } else { |
| 82 | attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2; |
| 83 | attrs->stepping += STEP_A0; |
| 84 | } |
| 85 | |
| 86 | attrs->microcode_patch = intel_microcode_find(); |
| 87 | attrs->address_bits = cpuid_eax(0x80000008) & 0xff; |
| 88 | detect_num_cpus(attrs); |
| 89 | |
| 90 | if (SHOW_PATTRS) { |
| 91 | printk(BIOS_DEBUG, "BYT: cpuid %08x cpus %d rid %02x step %s\n", |
| 92 | attrs->cpuid, attrs->num_cpus, attrs->revid, |
| 93 | (attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" : |
| 94 | stepping_str[attrs->stepping]); |
| 95 | } |
| 96 | |
Elyes HAOUAS | 419bfbc | 2018-10-01 08:47:51 +0200 | [diff] [blame] | 97 | fill_in_msr(&attrs->platform_id, IA32_PLATFORM_ID); |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 98 | fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO); |
Duncan Laurie | 6aa9f1f | 2013-11-07 12:47:35 -0800 | [diff] [blame] | 99 | |
| 100 | /* Set IA core speed ratio and voltages */ |
| 101 | msr = rdmsr(MSR_IACORE_RATIOS); |
| 102 | attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f; |
| 103 | attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f; |
| 104 | attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f; |
| 105 | msr = rdmsr(MSR_IACORE_TURBO_RATIOS); |
| 106 | attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */ |
| 107 | |
| 108 | msr = rdmsr(MSR_IACORE_VIDS); |
| 109 | attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f; |
| 110 | attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f; |
| 111 | attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f; |
| 112 | msr = rdmsr(MSR_IACORE_TURBO_VIDS); |
| 113 | attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */ |
| 114 | |
| 115 | /* Set bus clock speed */ |
| 116 | attrs->bclk_khz = bus_freq_khz(); |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 117 | } |
| 118 | |
Kyösti Mälkki | 4bd9187 | 2021-03-16 19:02:26 +0200 | [diff] [blame] | 119 | size_t size_of_dnvs(void) |
| 120 | { |
| 121 | return sizeof(struct device_nvs); |
| 122 | } |
| 123 | |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 124 | /* Save bit index for first enabled event in PM1_STS for \_SB._SWS */ |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 125 | static void pm_fill_gnvs(struct global_nvs *gnvs, const struct chipset_power_state *ps) |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 126 | { |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 127 | uint16_t pm1; |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 128 | int index; |
| 129 | |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 130 | pm1 = ps->pm1_sts & ps->pm1_en; |
| 131 | |
| 132 | /* Scan for first set bit in PM1 */ |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 133 | for (index = 0; index < 16; index++) { |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 134 | if (pm1 & 1) |
| 135 | break; |
| 136 | pm1 >>= 1; |
| 137 | } |
| 138 | |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 139 | if (index < 16) |
| 140 | gnvs->pm1i = index; |
Shawn Nematbakhsh | 51d787a | 2014-01-16 17:52:21 -0800 | [diff] [blame] | 141 | } |
| 142 | |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 143 | static void acpi_save_wake_source(void *unused) |
| 144 | { |
| 145 | const struct chipset_power_state *ps; |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 146 | struct global_nvs *gnvs; |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 147 | |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 148 | if (acpi_reset_gnvs_for_wake(&gnvs) < 0) |
| 149 | return; |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 150 | if (acpi_pm_state_for_wake(&ps) < 0) |
| 151 | return; |
| 152 | |
| 153 | pm_fill_gnvs(gnvs, ps); |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 154 | |
| 155 | printk(BIOS_DEBUG, "ACPI System Wake Source is PM1 Index %d\n", |
| 156 | gnvs->pm1i); |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 157 | } |
| 158 | |
Kyösti Mälkki | 4de1a31 | 2021-01-15 05:58:42 +0200 | [diff] [blame] | 159 | BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, acpi_save_wake_source, NULL); |
Kyösti Mälkki | d4b5825 | 2021-01-21 16:16:58 +0200 | [diff] [blame] | 160 | |
Kane Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 161 | static void baytrail_enable_2x_refresh_rate(void) |
| 162 | { |
| 163 | u32 reg; |
| 164 | reg = iosf_dunit_read(0x8); |
| 165 | reg = reg & ~0x7000; |
| 166 | reg = reg | 0x2000; |
| 167 | iosf_dunit_write(0x8, reg); |
| 168 | } |
| 169 | |
Kein Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 170 | void baytrail_init_pre_device(struct soc_intel_baytrail_config *config) |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 171 | { |
Kein Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 172 | struct soc_gpio_config *gpio_config; |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 173 | |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 174 | fill_in_pattrs(); |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 175 | |
Kane Chen | ba9b7bf | 2015-01-17 08:19:54 +0800 | [diff] [blame] | 176 | if (!config->disable_ddr_2x_refresh_rate) |
| 177 | baytrail_enable_2x_refresh_rate(); |
| 178 | |
Aaron Durbin | 1ce0b30 | 2013-10-10 12:47:47 -0500 | [diff] [blame] | 179 | /* Allow for SSE instructions to be executed. */ |
| 180 | write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT); |
| 181 | |
Aaron Durbin | ae5d83e | 2013-10-24 10:21:43 -0500 | [diff] [blame] | 182 | /* Run reference code. */ |
| 183 | baytrail_run_reference_code(); |
| 184 | |
Shawn Nematbakhsh | ebe3b3c | 2013-09-26 16:44:14 -0700 | [diff] [blame] | 185 | /* Get GPIO initial states from mainboard */ |
Kein Yuan | 3511023 | 2014-02-22 12:26:55 -0800 | [diff] [blame] | 186 | gpio_config = mainboard_get_gpios(); |
| 187 | setup_soc_gpios(gpio_config, config->enable_xdp_tap); |
Aaron Durbin | 6e77bee | 2013-10-30 15:25:42 -0500 | [diff] [blame] | 188 | |
Aaron Durbin | c626b74 | 2013-11-12 16:40:33 -0600 | [diff] [blame] | 189 | baytrail_init_scc(); |
Aaron Durbin | 452d31a | 2013-09-24 16:47:49 -0500 | [diff] [blame] | 190 | } |