Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Copyright 2019 Google LLC |
| 4 | */ |
| 5 | |
| 6 | #include <common.h> |
| 7 | #include <cpu.h> |
| 8 | #include <dm.h> |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 9 | #include <log.h> |
| 10 | #include <acpi/acpigen.h> |
| 11 | #include <acpi/acpi_table.h> |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 12 | #include <asm/cpu_common.h> |
| 13 | #include <asm/cpu_x86.h> |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 14 | #include <asm/global_data.h> |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 15 | #include <asm/intel_acpi.h> |
| 16 | #include <asm/msr.h> |
Simon Glass | f07f4b9 | 2020-11-04 09:57:15 -0700 | [diff] [blame] | 17 | #include <asm/mtrr.h> |
| 18 | #include <asm/arch/cpu.h> |
| 19 | #include <asm/arch/iomap.h> |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 20 | #include <dm/acpi.h> |
| 21 | |
| 22 | #define CSTATE_RES(address_space, width, offset, address) \ |
| 23 | { \ |
| 24 | .space_id = address_space, \ |
| 25 | .bit_width = width, \ |
| 26 | .bit_offset = offset, \ |
| 27 | .addrl = address, \ |
| 28 | } |
| 29 | |
| 30 | static struct acpi_cstate cstate_map[] = { |
| 31 | { |
| 32 | /* C1 */ |
| 33 | .ctype = 1, /* ACPI C1 */ |
| 34 | .latency = 1, |
| 35 | .power = 1000, |
| 36 | .resource = { |
| 37 | .space_id = ACPI_ADDRESS_SPACE_FIXED, |
| 38 | }, |
| 39 | }, { |
| 40 | .ctype = 2, /* ACPI C2 */ |
| 41 | .latency = 50, |
| 42 | .power = 10, |
| 43 | .resource = { |
| 44 | .space_id = ACPI_ADDRESS_SPACE_IO, |
| 45 | .bit_width = 8, |
| 46 | .addrl = 0x415, |
| 47 | }, |
| 48 | }, { |
| 49 | .ctype = 3, /* ACPI C3 */ |
| 50 | .latency = 150, |
| 51 | .power = 10, |
| 52 | .resource = { |
| 53 | .space_id = ACPI_ADDRESS_SPACE_IO, |
| 54 | .bit_width = 8, |
| 55 | .addrl = 0x419, |
| 56 | }, |
| 57 | }, |
| 58 | }; |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 59 | |
Simon Glass | 791fa45 | 2020-01-26 22:06:27 -0700 | [diff] [blame] | 60 | static int apl_get_info(const struct udevice *dev, struct cpu_info *info) |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 61 | { |
| 62 | return cpu_intel_get_info(info, INTEL_BCLK_MHZ); |
| 63 | } |
| 64 | |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 65 | static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) |
| 66 | { |
Simon Glass | 6feac81 | 2020-12-16 21:20:22 -0700 | [diff] [blame] | 67 | uint core_id = dev_seq(dev); |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 68 | int cores_per_package; |
| 69 | int ret; |
| 70 | |
| 71 | cores_per_package = cpu_get_cores_per_package(); |
| 72 | ret = acpi_generate_cpu_header(ctx, core_id, cstate_map, |
| 73 | ARRAY_SIZE(cstate_map)); |
| 74 | |
| 75 | /* Generate P-state tables */ |
| 76 | generate_p_state_entries(ctx, core_id, cores_per_package); |
| 77 | |
| 78 | /* Generate T-state tables */ |
| 79 | generate_t_state_entries(ctx, core_id, cores_per_package, NULL, 0); |
| 80 | |
| 81 | acpigen_pop_len(ctx); |
| 82 | |
| 83 | if (device_is_last_sibling(dev)) { |
| 84 | ret = acpi_generate_cpu_package_final(ctx, cores_per_package); |
| 85 | |
| 86 | if (ret) |
| 87 | return ret; |
| 88 | } |
| 89 | |
| 90 | return 0; |
| 91 | } |
| 92 | |
Simon Glass | f07f4b9 | 2020-11-04 09:57:15 -0700 | [diff] [blame] | 93 | static void update_fixed_mtrrs(void) |
| 94 | { |
| 95 | native_write_msr(MTRR_FIX_64K_00000_MSR, |
| 96 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 97 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 98 | native_write_msr(MTRR_FIX_16K_80000_MSR, |
| 99 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 100 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 101 | native_write_msr(MTRR_FIX_4K_E0000_MSR, |
| 102 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 103 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 104 | native_write_msr(MTRR_FIX_4K_E8000_MSR, |
| 105 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 106 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 107 | native_write_msr(MTRR_FIX_4K_F0000_MSR, |
| 108 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 109 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 110 | native_write_msr(MTRR_FIX_4K_F8000_MSR, |
| 111 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), |
| 112 | MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); |
| 113 | } |
| 114 | |
| 115 | static void setup_core_msrs(void) |
| 116 | { |
| 117 | wrmsrl(MSR_PMG_CST_CONFIG_CONTROL, |
| 118 | PKG_C_STATE_LIMIT_C2_MASK | CORE_C_STATE_LIMIT_C10_MASK | |
| 119 | IO_MWAIT_REDIRECT_MASK | CST_CFG_LOCK_MASK); |
| 120 | /* Power Management I/O base address for I/O trapping to C-states */ |
| 121 | wrmsrl(MSR_PMG_IO_CAPTURE_ADR, ACPI_PMIO_CST_REG | |
| 122 | (PMG_IO_BASE_CST_RNG_BLK_SIZE << 16)); |
| 123 | /* Disable C1E */ |
| 124 | msr_clrsetbits_64(MSR_POWER_CTL, 0x2, 0); |
| 125 | /* Disable support for MONITOR and MWAIT instructions */ |
| 126 | msr_clrsetbits_64(MSR_IA32_MISC_ENABLE, MISC_ENABLE_MWAIT, 0); |
| 127 | /* |
| 128 | * Enable and Lock the Advanced Encryption Standard (AES-NI) |
| 129 | * feature register |
| 130 | */ |
| 131 | msr_clrsetbits_64(MSR_FEATURE_CONFIG, FEATURE_CONFIG_RESERVED_MASK, |
| 132 | FEATURE_CONFIG_LOCK); |
| 133 | |
| 134 | update_fixed_mtrrs(); |
| 135 | } |
| 136 | |
| 137 | static int soc_core_init(void) |
| 138 | { |
| 139 | struct udevice *pmc; |
| 140 | int ret; |
| 141 | |
| 142 | /* Clear out pending MCEs */ |
| 143 | cpu_mca_configure(); |
| 144 | |
| 145 | /* Set core MSRs */ |
| 146 | setup_core_msrs(); |
| 147 | /* |
| 148 | * Enable ACPI PM timer emulation, which also lets microcode know |
| 149 | * location of ACPI_BASE_ADDRESS. This also enables other features |
| 150 | * implemented in microcode. |
| 151 | */ |
| 152 | ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc); |
| 153 | if (ret) |
| 154 | return log_msg_ret("PMC", ret); |
| 155 | enable_pm_timer_emulation(pmc); |
| 156 | |
| 157 | return 0; |
| 158 | } |
| 159 | |
| 160 | static int cpu_apl_probe(struct udevice *dev) |
| 161 | { |
| 162 | if (gd->flags & GD_FLG_RELOC) { |
| 163 | int ret; |
| 164 | |
| 165 | ret = soc_core_init(); |
| 166 | if (ret) |
| 167 | return log_ret(ret); |
| 168 | } |
| 169 | |
| 170 | return 0; |
| 171 | } |
| 172 | |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 173 | struct acpi_ops apl_cpu_acpi_ops = { |
| 174 | .fill_ssdt = acpi_cpu_fill_ssdt, |
| 175 | }; |
| 176 | |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 177 | static const struct cpu_ops cpu_x86_apl_ops = { |
| 178 | .get_desc = cpu_x86_get_desc, |
| 179 | .get_info = apl_get_info, |
Wolfgang Wallner | 4e3dfd5 | 2020-02-25 13:19:48 +0100 | [diff] [blame] | 180 | .get_count = cpu_x86_get_count, |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 181 | .get_vendor = cpu_x86_get_vendor, |
| 182 | }; |
| 183 | |
| 184 | static const struct udevice_id cpu_x86_apl_ids[] = { |
| 185 | { .compatible = "intel,apl-cpu" }, |
| 186 | { } |
| 187 | }; |
| 188 | |
Simon Glass | a055da8 | 2020-10-05 05:27:01 -0600 | [diff] [blame] | 189 | U_BOOT_DRIVER(intel_apl_cpu) = { |
| 190 | .name = "intel_apl_cpu", |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 191 | .id = UCLASS_CPU, |
| 192 | .of_match = cpu_x86_apl_ids, |
| 193 | .bind = cpu_x86_bind, |
Simon Glass | f07f4b9 | 2020-11-04 09:57:15 -0700 | [diff] [blame] | 194 | .probe = cpu_apl_probe, |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 195 | .ops = &cpu_x86_apl_ops, |
Simon Glass | 1eba121 | 2020-09-22 12:45:21 -0600 | [diff] [blame] | 196 | ACPI_OPS_PTR(&apl_cpu_acpi_ops) |
Simon Glass | fcfd26e | 2019-12-08 17:40:14 -0700 | [diff] [blame] | 197 | .flags = DM_FLAG_PRE_RELOC, |
| 198 | }; |