Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Copyright 2019 Google LLC |
| 4 | * Written by Simon Glass <sjg@chromium.org> |
| 5 | */ |
| 6 | |
| 7 | #include <common.h> |
| 8 | #include <acpi_s3.h> |
| 9 | #include <binman.h> |
| 10 | #include <dm.h> |
| 11 | #include <irq.h> |
| 12 | #include <asm/intel_pinctrl.h> |
| 13 | #include <asm/io.h> |
| 14 | #include <asm/intel_regs.h> |
| 15 | #include <asm/msr.h> |
| 16 | #include <asm/msr-index.h> |
| 17 | #include <asm/pci.h> |
| 18 | #include <asm/arch/cpu.h> |
| 19 | #include <asm/arch/systemagent.h> |
| 20 | #include <asm/arch/fsp/fsp_configs.h> |
| 21 | #include <asm/arch/fsp/fsp_s_upd.h> |
| 22 | |
| 23 | #define PCH_P2SB_E0 0xe0 |
| 24 | #define HIDE_BIT BIT(0) |
| 25 | |
| 26 | #define INTEL_GSPI_MAX 3 |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 27 | #define MAX_USB2_PORTS 8 |
| 28 | |
| 29 | enum { |
| 30 | CHIPSET_LOCKDOWN_FSP = 0, /* FSP handles locking per UPDs */ |
| 31 | CHIPSET_LOCKDOWN_COREBOOT, /* coreboot handles locking */ |
| 32 | }; |
| 33 | |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 34 | /* Serial IRQ control. SERIRQ_QUIET is the default (0) */ |
| 35 | enum serirq_mode { |
| 36 | SERIRQ_QUIET, |
| 37 | SERIRQ_CONTINUOUS, |
| 38 | SERIRQ_OFF, |
| 39 | }; |
| 40 | |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 41 | struct gspi_cfg { |
| 42 | /* Bus speed in MHz */ |
| 43 | u32 speed_mhz; |
| 44 | /* Bus should be enabled prior to ramstage with temporary base */ |
| 45 | u8 early_init; |
| 46 | }; |
| 47 | |
| 48 | /* |
| 49 | * This structure will hold data required by common blocks. |
| 50 | * These are soc specific configurations which will be filled by soc. |
| 51 | * We'll fill this structure once during init and use the data in common block. |
| 52 | */ |
| 53 | struct soc_intel_common_config { |
| 54 | int chipset_lockdown; |
| 55 | struct gspi_cfg gspi[INTEL_GSPI_MAX]; |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 56 | }; |
| 57 | |
| 58 | enum pnp_settings { |
| 59 | PNP_PERF, |
| 60 | PNP_POWER, |
| 61 | PNP_PERF_POWER, |
| 62 | }; |
| 63 | |
| 64 | struct usb2_eye_per_port { |
| 65 | u8 per_port_tx_pe_half; |
| 66 | u8 per_port_pe_txi_set; |
| 67 | u8 per_port_txi_set; |
| 68 | u8 hs_skew_sel; |
| 69 | u8 usb_tx_emphasis_en; |
| 70 | u8 per_port_rxi_set; |
| 71 | u8 hs_npre_drv_sel; |
| 72 | u8 override_en; |
| 73 | }; |
| 74 | |
| 75 | struct apl_config { |
| 76 | /* Common structure containing soc config data required by common code*/ |
| 77 | struct soc_intel_common_config common_soc_config; |
| 78 | |
| 79 | /* |
| 80 | * Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has |
| 81 | * four CLKREQ inputs, but six root ports. Root ports without an |
| 82 | * associated CLKREQ signal must be marked with "CLKREQ_DISABLED" |
| 83 | */ |
| 84 | u8 pcie_rp_clkreq_pin[MAX_PCIE_PORTS]; |
| 85 | |
| 86 | /* Enable/disable hot-plug for root ports (0 = disable, 1 = enable) */ |
| 87 | u8 pcie_rp_hotplug_enable[MAX_PCIE_PORTS]; |
| 88 | |
| 89 | /* De-emphasis enable configuration for each PCIe root port */ |
| 90 | u8 pcie_rp_deemphasis_enable[MAX_PCIE_PORTS]; |
| 91 | |
| 92 | /* |
| 93 | * [14:8] DDR mode Number of dealy elements.Each = 125pSec. |
| 94 | * [6:0] SDR mode Number of dealy elements.Each = 125pSec. |
| 95 | */ |
| 96 | u32 emmc_tx_cmd_cntl; |
| 97 | |
| 98 | /* |
| 99 | * [14:8] HS400 mode Number of dealy elements.Each = 125pSec. |
| 100 | * [6:0] SDR104/HS200 mode Number of dealy elements.Each = 125pSec. |
| 101 | */ |
| 102 | u32 emmc_tx_data_cntl1; |
| 103 | |
| 104 | /* |
| 105 | * [30:24] SDR50 mode Number of dealy elements.Each = 125pSec. |
| 106 | * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec. |
| 107 | * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec. |
| 108 | * [6:0] SDR12/Compatibility mode Number of dealy elements. |
| 109 | * Each = 125pSec. |
| 110 | */ |
| 111 | u32 emmc_tx_data_cntl2; |
| 112 | |
| 113 | /* |
| 114 | * [30:24] SDR50 mode Number of dealy elements.Each = 125pSec. |
| 115 | * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec. |
| 116 | * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec. |
| 117 | * [6:0] SDR12/Compatibility mode Number of dealy elements. |
| 118 | * Each = 125pSec. |
| 119 | */ |
| 120 | u32 emmc_rx_cmd_data_cntl1; |
| 121 | |
| 122 | /* |
| 123 | * [14:8] HS400 mode 1 Number of dealy elements.Each = 125pSec. |
| 124 | * [6:0] HS400 mode 2 Number of dealy elements.Each = 125pSec. |
| 125 | */ |
| 126 | u32 emmc_rx_strobe_cntl; |
| 127 | |
| 128 | /* |
| 129 | * [13:8] Auto Tuning mode Number of dealy elements.Each = 125pSec. |
| 130 | * [6:0] SDR104/HS200 Number of dealy elements.Each = 125pSec. |
| 131 | */ |
| 132 | u32 emmc_rx_cmd_data_cntl2; |
| 133 | |
| 134 | /* Select the eMMC max speed allowed */ |
| 135 | u32 emmc_host_max_speed; |
| 136 | |
| 137 | /* Specifies on which IRQ the SCI will internally appear */ |
| 138 | u32 sci_irq; |
| 139 | |
| 140 | /* Configure serial IRQ (SERIRQ) line */ |
| 141 | enum serirq_mode serirq_mode; |
| 142 | |
| 143 | /* Configure LPSS S0ix Enable */ |
| 144 | bool lpss_s0ix_enable; |
| 145 | |
| 146 | /* Enable DPTF support */ |
| 147 | bool dptf_enable; |
| 148 | |
| 149 | /* TCC activation offset value in degrees Celsius */ |
| 150 | int tcc_offset; |
| 151 | |
| 152 | /* |
| 153 | * Configure Audio clk gate and power gate |
| 154 | * IOSF-SB port ID 92 offset 0x530 [5] and [3] |
| 155 | */ |
| 156 | bool hdaudio_clk_gate_enable; |
| 157 | bool hdaudio_pwr_gate_enable; |
| 158 | bool hdaudio_bios_config_lockdown; |
| 159 | |
| 160 | /* SLP S3 minimum assertion width */ |
| 161 | int slp_s3_assertion_width_usecs; |
| 162 | |
| 163 | /* GPIO pin for PERST_0 */ |
| 164 | u32 prt0_gpio; |
| 165 | |
| 166 | /* USB2 eye diagram settings per port */ |
| 167 | struct usb2_eye_per_port usb2eye[MAX_USB2_PORTS]; |
| 168 | |
| 169 | /* GPIO SD card detect pin */ |
| 170 | unsigned int sdcard_cd_gpio; |
| 171 | |
| 172 | /* |
| 173 | * PRMRR size setting with three options |
| 174 | * 0x02000000 - 32MiB |
| 175 | * 0x04000000 - 64MiB |
| 176 | * 0x08000000 - 128MiB |
| 177 | */ |
| 178 | u32 PrmrrSize; |
| 179 | |
| 180 | /* |
| 181 | * Enable SGX feature. |
| 182 | * Enabling SGX feature is 2 step process, |
| 183 | * (1) set sgx_enable = 1 |
| 184 | * (2) set PrmrrSize to supported size |
| 185 | */ |
| 186 | bool sgx_enable; |
| 187 | |
| 188 | /* |
| 189 | * Select PNP Settings. |
| 190 | * (0) Performance, |
| 191 | * (1) Power |
| 192 | * (2) Power & Performance |
| 193 | */ |
| 194 | enum pnp_settings pnp_settings; |
| 195 | |
| 196 | /* |
| 197 | * PMIC PCH_PWROK delay configuration - IPC Configuration |
| 198 | * Upd for changing PCH_PWROK delay configuration : I2C_Slave_Address |
| 199 | * (31:24) + Register_Offset (23:16) + OR Value (15:8) + AND Value (7:0) |
| 200 | */ |
| 201 | u32 pmic_pmc_ipc_ctrl; |
| 202 | |
| 203 | /* |
| 204 | * Options to disable XHCI Link Compliance Mode. Default is FALSE to not |
| 205 | * disable Compliance Mode. Set TRUE to disable Compliance Mode. |
| 206 | * 0:FALSE(Default), 1:True. |
| 207 | */ |
| 208 | bool disable_compliance_mode; |
| 209 | |
| 210 | /* |
| 211 | * Options to change USB3 ModPhy setting for the Integrated Filter (IF) |
| 212 | * value. Default is 0 to not changing default IF value (0x12). Set |
| 213 | * value with the range from 0x01 to 0xff to change IF value. |
| 214 | */ |
| 215 | u32 mod_phy_if_value; |
| 216 | |
| 217 | /* |
| 218 | * Options to bump USB3 LDO voltage. Default is FALSE to not increasing |
| 219 | * LDO voltage. Set TRUE to increase LDO voltage with 40mV. |
| 220 | * 0:FALSE (default), 1:True. |
| 221 | */ |
| 222 | bool mod_phy_voltage_bump; |
| 223 | |
| 224 | /* |
| 225 | * Options to adjust PMIC Vdd2 voltage. Default is 0 to not adjusting |
| 226 | * the PMIC Vdd2 default voltage 1.20v. Upd for changing Vdd2 Voltage |
| 227 | * configuration: I2C_Slave_Address (31:23) + Register_Offset (23:16) |
| 228 | * + OR Value (15:8) + AND Value (7:0) through BUCK5_VID[3:2]: |
| 229 | * 00=1.10v, 01=1.15v, 10=1.24v, 11=1.20v (default). |
| 230 | */ |
| 231 | u32 pmic_vdd2_voltage; |
| 232 | |
| 233 | /* Option to enable VTD feature */ |
| 234 | bool enable_vtd; |
| 235 | }; |
| 236 | |
| 237 | static int get_config(struct udevice *dev, struct apl_config *apl) |
| 238 | { |
| 239 | const u8 *ptr; |
| 240 | ofnode node; |
| 241 | u32 emmc[4]; |
| 242 | int ret; |
| 243 | |
| 244 | memset(apl, '\0', sizeof(*apl)); |
| 245 | |
| 246 | node = dev_read_subnode(dev, "fsp-s"); |
| 247 | if (!ofnode_valid(node)) |
| 248 | return log_msg_ret("fsp-s settings", -ENOENT); |
| 249 | |
| 250 | ptr = ofnode_read_u8_array_ptr(node, "pcie-rp-clkreq-pin", |
| 251 | MAX_PCIE_PORTS); |
| 252 | if (!ptr) |
| 253 | return log_msg_ret("pcie-rp-clkreq-pin", -EINVAL); |
| 254 | memcpy(apl->pcie_rp_clkreq_pin, ptr, MAX_PCIE_PORTS); |
| 255 | |
| 256 | ret = ofnode_read_u32(node, "prt0-gpio", &apl->prt0_gpio); |
| 257 | if (ret) |
| 258 | return log_msg_ret("prt0-gpio", ret); |
| 259 | ret = ofnode_read_u32(node, "sdcard-cd-gpio", &apl->sdcard_cd_gpio); |
| 260 | if (ret) |
| 261 | return log_msg_ret("sdcard-cd-gpio", ret); |
| 262 | |
| 263 | ret = ofnode_read_u32_array(node, "emmc", emmc, ARRAY_SIZE(emmc)); |
| 264 | if (ret) |
| 265 | return log_msg_ret("emmc", ret); |
| 266 | apl->emmc_tx_data_cntl1 = emmc[0]; |
| 267 | apl->emmc_tx_data_cntl2 = emmc[1]; |
| 268 | apl->emmc_rx_cmd_data_cntl1 = emmc[2]; |
| 269 | apl->emmc_rx_cmd_data_cntl2 = emmc[3]; |
| 270 | |
| 271 | apl->dptf_enable = ofnode_read_bool(node, "dptf-enable"); |
| 272 | |
| 273 | apl->hdaudio_clk_gate_enable = ofnode_read_bool(node, |
| 274 | "hdaudio-clk-gate-enable"); |
| 275 | apl->hdaudio_pwr_gate_enable = ofnode_read_bool(node, |
| 276 | "hdaudio-pwr-gate-enable"); |
| 277 | apl->hdaudio_bios_config_lockdown = ofnode_read_bool(node, |
| 278 | "hdaudio-bios-config-lockdown"); |
| 279 | apl->lpss_s0ix_enable = ofnode_read_bool(node, "lpss-s0ix-enable"); |
| 280 | |
| 281 | /* Santa */ |
| 282 | apl->usb2eye[1].per_port_pe_txi_set = 7; |
| 283 | apl->usb2eye[1].per_port_txi_set = 2; |
| 284 | |
| 285 | return 0; |
| 286 | } |
| 287 | |
| 288 | static void apl_fsp_silicon_init_params_cb(struct apl_config *apl, |
| 289 | struct fsp_s_config *cfg) |
| 290 | { |
| 291 | u8 port; |
| 292 | |
| 293 | for (port = 0; port < MAX_USB2_PORTS; port++) { |
| 294 | if (apl->usb2eye[port].per_port_tx_pe_half) |
| 295 | cfg->port_usb20_per_port_tx_pe_half[port] = |
| 296 | apl->usb2eye[port].per_port_tx_pe_half; |
| 297 | |
| 298 | if (apl->usb2eye[port].per_port_pe_txi_set) |
| 299 | cfg->port_usb20_per_port_pe_txi_set[port] = |
| 300 | apl->usb2eye[port].per_port_pe_txi_set; |
| 301 | |
| 302 | if (apl->usb2eye[port].per_port_txi_set) |
| 303 | cfg->port_usb20_per_port_txi_set[port] = |
| 304 | apl->usb2eye[port].per_port_txi_set; |
| 305 | |
| 306 | if (apl->usb2eye[port].hs_skew_sel) |
| 307 | cfg->port_usb20_hs_skew_sel[port] = |
| 308 | apl->usb2eye[port].hs_skew_sel; |
| 309 | |
| 310 | if (apl->usb2eye[port].usb_tx_emphasis_en) |
| 311 | cfg->port_usb20_i_usb_tx_emphasis_en[port] = |
| 312 | apl->usb2eye[port].usb_tx_emphasis_en; |
| 313 | |
| 314 | if (apl->usb2eye[port].per_port_rxi_set) |
| 315 | cfg->port_usb20_per_port_rxi_set[port] = |
| 316 | apl->usb2eye[port].per_port_rxi_set; |
| 317 | |
| 318 | if (apl->usb2eye[port].hs_npre_drv_sel) |
| 319 | cfg->port_usb20_hs_npre_drv_sel[port] = |
| 320 | apl->usb2eye[port].hs_npre_drv_sel; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | int fsps_update_config(struct udevice *dev, ulong rom_offset, |
| 325 | struct fsps_upd *upd) |
| 326 | { |
| 327 | struct fsp_s_config *cfg = &upd->config; |
| 328 | struct apl_config *apl; |
| 329 | struct binman_entry vbt; |
| 330 | void *buf; |
| 331 | int ret; |
| 332 | |
| 333 | ret = binman_entry_find("intel-vbt", &vbt); |
| 334 | if (ret) |
| 335 | return log_msg_ret("Cannot find VBT", ret); |
| 336 | vbt.image_pos += rom_offset; |
| 337 | buf = malloc(vbt.size); |
| 338 | if (!buf) |
| 339 | return log_msg_ret("Alloc VBT", -ENOMEM); |
| 340 | |
| 341 | /* |
| 342 | * Load VBT before devicetree-specific config. This only supports |
| 343 | * memory-mapped SPI at present. |
| 344 | */ |
| 345 | bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi"); |
| 346 | memcpy(buf, (void *)vbt.image_pos, vbt.size); |
| 347 | bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI); |
| 348 | if (*(u32 *)buf != VBT_SIGNATURE) |
| 349 | return log_msg_ret("VBT signature", -EINVAL); |
| 350 | cfg->graphics_config_ptr = (ulong)buf; |
| 351 | |
| 352 | apl = malloc(sizeof(*apl)); |
| 353 | if (!apl) |
| 354 | return log_msg_ret("config", -ENOMEM); |
| 355 | get_config(dev, apl); |
| 356 | |
| 357 | cfg->ish_enable = 0; |
| 358 | cfg->enable_sata = 0; |
| 359 | cfg->pcie_root_port_en[2] = 0; |
| 360 | cfg->pcie_rp_hot_plug[2] = 0; |
| 361 | cfg->pcie_root_port_en[3] = 0; |
| 362 | cfg->pcie_rp_hot_plug[3] = 0; |
| 363 | cfg->pcie_root_port_en[4] = 0; |
| 364 | cfg->pcie_rp_hot_plug[4] = 0; |
| 365 | cfg->pcie_root_port_en[5] = 0; |
| 366 | cfg->pcie_rp_hot_plug[5] = 0; |
| 367 | cfg->pcie_root_port_en[1] = 0; |
| 368 | cfg->pcie_rp_hot_plug[1] = 0; |
| 369 | cfg->usb_otg = 0; |
| 370 | cfg->i2c6_enable = 0; |
| 371 | cfg->i2c7_enable = 0; |
| 372 | cfg->hsuart3_enable = 0; |
| 373 | cfg->spi1_enable = 0; |
| 374 | cfg->spi2_enable = 0; |
| 375 | cfg->sdio_enabled = 0; |
| 376 | |
| 377 | memcpy(cfg->pcie_rp_clk_req_number, apl->pcie_rp_clkreq_pin, |
| 378 | sizeof(cfg->pcie_rp_clk_req_number)); |
| 379 | |
| 380 | memcpy(cfg->pcie_rp_hot_plug, apl->pcie_rp_hotplug_enable, |
| 381 | sizeof(cfg->pcie_rp_hot_plug)); |
| 382 | |
| 383 | switch (apl->serirq_mode) { |
| 384 | case SERIRQ_QUIET: |
| 385 | cfg->sirq_enable = 1; |
| 386 | cfg->sirq_mode = 0; |
| 387 | break; |
| 388 | case SERIRQ_CONTINUOUS: |
| 389 | cfg->sirq_enable = 1; |
| 390 | cfg->sirq_mode = 1; |
| 391 | break; |
| 392 | case SERIRQ_OFF: |
| 393 | default: |
| 394 | cfg->sirq_enable = 0; |
| 395 | break; |
| 396 | } |
| 397 | |
| 398 | if (apl->emmc_tx_cmd_cntl) |
| 399 | cfg->emmc_tx_cmd_cntl = apl->emmc_tx_cmd_cntl; |
| 400 | if (apl->emmc_tx_data_cntl1) |
| 401 | cfg->emmc_tx_data_cntl1 = apl->emmc_tx_data_cntl1; |
| 402 | if (apl->emmc_tx_data_cntl2) |
| 403 | cfg->emmc_tx_data_cntl2 = apl->emmc_tx_data_cntl2; |
| 404 | if (apl->emmc_rx_cmd_data_cntl1) |
| 405 | cfg->emmc_rx_cmd_data_cntl1 = apl->emmc_rx_cmd_data_cntl1; |
| 406 | if (apl->emmc_rx_strobe_cntl) |
| 407 | cfg->emmc_rx_strobe_cntl = apl->emmc_rx_strobe_cntl; |
| 408 | if (apl->emmc_rx_cmd_data_cntl2) |
| 409 | cfg->emmc_rx_cmd_data_cntl2 = apl->emmc_rx_cmd_data_cntl2; |
| 410 | if (apl->emmc_host_max_speed) |
| 411 | cfg->e_mmc_host_max_speed = apl->emmc_host_max_speed; |
| 412 | |
| 413 | cfg->lpss_s0ix_enable = apl->lpss_s0ix_enable; |
| 414 | |
| 415 | cfg->skip_mp_init = true; |
| 416 | |
| 417 | /* Disable setting of EISS bit in FSP */ |
| 418 | cfg->spi_eiss = 0; |
| 419 | |
| 420 | /* Disable FSP from locking access to the RTC NVRAM */ |
| 421 | cfg->rtc_lock = 0; |
| 422 | |
| 423 | /* Enable Audio clk gate and power gate */ |
| 424 | cfg->hd_audio_clk_gate = apl->hdaudio_clk_gate_enable; |
| 425 | cfg->hd_audio_pwr_gate = apl->hdaudio_pwr_gate_enable; |
| 426 | /* Bios config lockdown Audio clk and power gate */ |
| 427 | cfg->bios_cfg_lock_down = apl->hdaudio_bios_config_lockdown; |
| 428 | apl_fsp_silicon_init_params_cb(apl, cfg); |
| 429 | |
| 430 | cfg->usb_otg = true; |
| 431 | cfg->vtd_enable = apl->enable_vtd; |
| 432 | |
| 433 | return 0; |
| 434 | } |
| 435 | |
| 436 | static void p2sb_set_hide_bit(pci_dev_t dev, int hide) |
| 437 | { |
| 438 | pci_x86_clrset_config(dev, PCH_P2SB_E0 + 1, HIDE_BIT, |
| 439 | hide ? HIDE_BIT : 0, PCI_SIZE_8); |
| 440 | } |
| 441 | |
| 442 | /* Configure package power limits */ |
| 443 | static int set_power_limits(struct udevice *dev) |
| 444 | { |
| 445 | msr_t rapl_msr_reg, limit; |
| 446 | u32 power_unit; |
| 447 | u32 tdp, min_power, max_power; |
| 448 | u32 pl2_val; |
| 449 | u32 override_tdp[2]; |
| 450 | int ret; |
| 451 | |
| 452 | /* Get units */ |
| 453 | rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT); |
| 454 | power_unit = 1 << (rapl_msr_reg.lo & 0xf); |
| 455 | |
| 456 | /* Get power defaults for this SKU */ |
| 457 | rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU); |
| 458 | tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK; |
| 459 | pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK; |
| 460 | min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK; |
| 461 | max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK; |
| 462 | |
| 463 | if (min_power > 0 && tdp < min_power) |
| 464 | tdp = min_power; |
| 465 | |
| 466 | if (max_power > 0 && tdp > max_power) |
| 467 | tdp = max_power; |
| 468 | |
| 469 | ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp, |
| 470 | ARRAY_SIZE(override_tdp)); |
| 471 | if (ret) |
| 472 | return log_msg_ret("tdp-pl-override-mw", ret); |
| 473 | |
| 474 | /* Set PL1 override value */ |
| 475 | if (override_tdp[0]) |
| 476 | tdp = override_tdp[0] * power_unit / 1000; |
| 477 | |
| 478 | /* Set PL2 override value */ |
| 479 | if (override_tdp[1]) |
| 480 | pl2_val = override_tdp[1] * power_unit / 1000; |
| 481 | |
| 482 | /* Set long term power limit to TDP */ |
| 483 | limit.lo = tdp & PKG_POWER_LIMIT_MASK; |
| 484 | /* Set PL1 Pkg Power clamp bit */ |
| 485 | limit.lo |= PKG_POWER_LIMIT_CLAMP; |
| 486 | |
| 487 | limit.lo |= PKG_POWER_LIMIT_EN; |
| 488 | limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT & |
| 489 | PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT; |
| 490 | |
| 491 | /* Set short term power limit PL2 */ |
| 492 | limit.hi = pl2_val & PKG_POWER_LIMIT_MASK; |
| 493 | limit.hi |= PKG_POWER_LIMIT_EN; |
| 494 | |
| 495 | /* Program package power limits in RAPL MSR */ |
| 496 | msr_write(MSR_PKG_POWER_LIMIT, limit); |
| 497 | log_info("RAPL PL1 %d.%dW\n", tdp / power_unit, |
| 498 | 100 * (tdp % power_unit) / power_unit); |
| 499 | log_info("RAPL PL2 %d.%dW\n", pl2_val / power_unit, |
| 500 | 100 * (pl2_val % power_unit) / power_unit); |
| 501 | |
| 502 | /* |
| 503 | * Sett RAPL MMIO register for Power limits. RAPL driver is using MSR |
| 504 | * instead of MMIO, so disable LIMIT_EN bit for MMIO |
| 505 | */ |
| 506 | writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL)); |
| 507 | writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4)); |
| 508 | |
| 509 | return 0; |
| 510 | } |
| 511 | |
| 512 | int p2sb_unhide(void) |
| 513 | { |
| 514 | pci_dev_t dev = PCI_BDF(0, 0xd, 0); |
| 515 | ulong val; |
| 516 | |
| 517 | p2sb_set_hide_bit(dev, 0); |
| 518 | |
| 519 | pci_x86_read_config(dev, PCI_VENDOR_ID, &val, PCI_SIZE_16); |
| 520 | |
| 521 | if (val != PCI_VENDOR_ID_INTEL) |
| 522 | return log_msg_ret("p2sb unhide", -EIO); |
| 523 | |
| 524 | return 0; |
| 525 | } |
| 526 | |
| 527 | /* Overwrites the SCI IRQ if another IRQ number is given by device tree */ |
| 528 | static void set_sci_irq(void) |
| 529 | { |
| 530 | /* Skip this for now */ |
| 531 | } |
| 532 | |
| 533 | int arch_fsps_preinit(void) |
| 534 | { |
| 535 | struct udevice *itss; |
| 536 | int ret; |
| 537 | |
Simon Glass | 21bb12a | 2020-02-06 09:54:58 -0700 | [diff] [blame^] | 538 | ret = irq_first_device_type(X86_IRQT_ITSS, &itss); |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 539 | if (ret) |
| 540 | return log_msg_ret("no itss", ret); |
| 541 | /* |
| 542 | * Snapshot the current GPIO IRQ polarities. FSP is setting a default |
| 543 | * policy that doesn't honour boards' requirements |
| 544 | */ |
| 545 | irq_snapshot_polarities(itss); |
| 546 | |
| 547 | /* |
| 548 | * Clear the GPI interrupt status and enable registers. These |
| 549 | * registers do not get reset to default state when booting from S5. |
| 550 | */ |
| 551 | ret = pinctrl_gpi_clear_int_cfg(); |
| 552 | if (ret) |
| 553 | return log_msg_ret("gpi_clear", ret); |
| 554 | |
| 555 | return 0; |
| 556 | } |
| 557 | |
| 558 | int arch_fsp_init_r(void) |
| 559 | { |
| 560 | #ifdef CONFIG_HAVE_ACPI_RESUME |
| 561 | bool s3wake = gd->arch.prev_sleep_state == ACPI_S3; |
| 562 | #else |
| 563 | bool s3wake = false; |
| 564 | #endif |
| 565 | struct udevice *dev, *itss; |
| 566 | int ret; |
| 567 | |
| 568 | /* |
| 569 | * This must be called before any devices are probed. Put any probing |
| 570 | * into arch_fsps_preinit() above. |
| 571 | * |
| 572 | * We don't use CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH here since it will |
| 573 | * force PCI to be probed. |
| 574 | */ |
| 575 | ret = fsp_silicon_init(s3wake, false); |
| 576 | if (ret) |
| 577 | return ret; |
| 578 | |
Simon Glass | 21bb12a | 2020-02-06 09:54:58 -0700 | [diff] [blame^] | 579 | ret = irq_first_device_type(X86_IRQT_ITSS, &itss); |
Simon Glass | 42bf7db | 2019-12-08 17:40:19 -0700 | [diff] [blame] | 580 | if (ret) |
| 581 | return log_msg_ret("no itss", ret); |
| 582 | /* Restore GPIO IRQ polarities back to previous settings */ |
| 583 | irq_restore_polarities(itss); |
| 584 | |
| 585 | /* soc_init() */ |
| 586 | ret = p2sb_unhide(); |
| 587 | if (ret) |
| 588 | return log_msg_ret("unhide p2sb", ret); |
| 589 | |
| 590 | /* Set RAPL MSR for Package power limits*/ |
| 591 | ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); |
| 592 | if (ret) |
| 593 | return log_msg_ret("Cannot get northbridge", ret); |
| 594 | set_power_limits(dev); |
| 595 | |
| 596 | /* |
| 597 | * FSP-S routes SCI to IRQ 9. With the help of this function you can |
| 598 | * select another IRQ for SCI. |
| 599 | */ |
| 600 | set_sci_irq(); |
| 601 | |
| 602 | return 0; |
| 603 | } |