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