2 * This file is part of the coreboot project.
4 * Copyright (C) 2018-2019 Intel Corporation.
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.
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.
16 #include <console/console.h>
17 #include <device/device.h>
18 #include <device/pci.h>
21 #include <intelblocks/lpss.h>
22 #include <intelblocks/xdci.h>
23 #include <intelpch/lockdown.h>
24 #include <soc/intel/common/vbt.h>
25 #include <soc/pci_devs.h>
26 #include <soc/ramstage.h>
31 static const pci_devfn_t serial_io_dev
[] = {
47 * Given an enum for PCH_SERIAL_IO_MODE, 1 needs to be subtracted to get the FSP
48 * UPD expected value for Serial IO since valid enum index starts from 1.
50 #define PCH_SERIAL_IO_INDEX(x) ((x) - 1)
52 static uint8_t get_param_value(const config_t
*config
, uint32_t dev_offset
)
56 dev
= pcidev_path_on_root(serial_io_dev
[dev_offset
]);
57 if (!dev
|| !dev
->enabled
)
58 return PCH_SERIAL_IO_INDEX(PchSerialIoDisabled
);
60 if ((config
->SerialIoDevMode
[dev_offset
] >= PchSerialIoMax
) ||
61 (config
->SerialIoDevMode
[dev_offset
] == PchSerialIoNotInitialized
))
62 return PCH_SERIAL_IO_INDEX(PchSerialIoPci
);
65 * Correct Enum index starts from 1, so subtract 1 while returning value
67 return PCH_SERIAL_IO_INDEX(config
->SerialIoDevMode
[dev_offset
]);
70 #if CONFIG(SOC_INTEL_COMETLAKE)
71 static void parse_devicetree_param(const config_t
*config
, FSP_S_CONFIG
*params
)
73 uint32_t dev_offset
= 0;
76 for (i
= 0; i
< CONFIG_SOC_INTEL_I2C_DEV_MAX
; i
++, dev_offset
++) {
77 params
->SerialIoI2cMode
[i
] =
78 get_param_value(config
, dev_offset
);
81 for (i
= 0; i
< CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX
; i
++,
83 params
->SerialIoSpiMode
[i
] =
84 get_param_value(config
, dev_offset
);
87 for (i
= 0; i
< SOC_INTEL_CML_UART_DEV_MAX
; i
++, dev_offset
++) {
88 params
->SerialIoUartMode
[i
] =
89 get_param_value(config
, dev_offset
);
93 static void parse_devicetree_param(const config_t
*config
, FSP_S_CONFIG
*params
)
95 for (int i
= 0; i
< ARRAY_SIZE(serial_io_dev
); i
++)
96 params
->SerialIoDevMode
[i
] = get_param_value(config
, i
);
100 static void parse_devicetree(FSP_S_CONFIG
*params
)
102 const config_t
*config
= config_of_soc();
104 parse_devicetree_param(config
, params
);
107 /* Ignore LTR value for GBE devices */
108 static void ignore_gbe_ltr(void)
111 uint8_t *pmcbase
= pmc_mmio_regs();
113 reg8
= read8(pmcbase
+ LTR_IGN
);
115 write8(pmcbase
+ LTR_IGN
, reg8
);
118 static void configure_gspi_cs(int idx
, const config_t
*config
,
119 uint8_t *polarity
, uint8_t *enable
,
124 /* If speed_mhz is set, infer that the port should be configured */
125 if (config
->common_soc_config
.gspi
[idx
].speed_mhz
!= 0) {
126 if (gspi_get_soc_spi_cfg(idx
, &cfg
) == 0) {
127 if (cfg
.cs_polarity
== SPI_POLARITY_LOW
)
132 if (defaultcs
!= NULL
)
140 /* UPD parameters to be initialized before SiliconInit */
141 void platform_fsp_silicon_init_params_cb(FSPS_UPD
*supd
)
144 FSP_S_CONFIG
*params
= &supd
->FspsConfig
;
145 FSP_S_TEST_CONFIG
*tconfig
= &supd
->FspsTestConfig
;
148 config_t
*config
= config_of_soc();
150 /* Parse device tree and enable/disable devices */
151 parse_devicetree(params
);
153 /* Load VBT before devicetree-specific config. */
154 params
->GraphicsConfigPtr
= (uintptr_t)vbt_get();
156 /* Set USB OC pin to 0 first */
157 for (i
= 0; i
< ARRAY_SIZE(params
->Usb2OverCurrentPin
); i
++) {
158 params
->Usb2OverCurrentPin
[i
] = 0;
161 for (i
= 0; i
< ARRAY_SIZE(params
->Usb3OverCurrentPin
); i
++) {
162 params
->Usb3OverCurrentPin
[i
] = 0;
165 mainboard_silicon_init_params(params
);
167 /* Set PsysPmax if it is available from DT */
168 if (config
->psys_pmax
) {
169 printk(BIOS_DEBUG
, "psys_pmax = %dW\n", config
->psys_pmax
);
170 /* PsysPmax is in unit of 1/8 Watt */
171 tconfig
->PsysPmax
= config
->psys_pmax
* 8;
174 /* Unlock upper 8 bytes of RTC RAM */
175 params
->PchLockDownRtcMemoryLock
= 0;
178 dev
= pcidev_path_on_root(PCH_DEVFN_SATA
);
180 params
->SataEnable
= 0;
182 params
->SataEnable
= dev
->enabled
;
183 params
->SataMode
= config
->SataMode
;
184 params
->SataSalpSupport
= config
->SataSalpSupport
;
185 memcpy(params
->SataPortsEnable
, config
->SataPortsEnable
,
186 sizeof(params
->SataPortsEnable
));
187 memcpy(params
->SataPortsDevSlp
, config
->SataPortsDevSlp
,
188 sizeof(params
->SataPortsDevSlp
));
189 #if CONFIG(SOC_INTEL_COMETLAKE)
190 memcpy(params
->SataPortsDevSlpResetConfig
,
191 config
->SataPortsDevSlpResetConfig
,
192 sizeof(params
->SataPortsDevSlpResetConfig
));
197 dev
= pcidev_path_on_root(PCH_DEVFN_GBE
);
199 params
->PchLanEnable
= 0;
201 params
->PchLanEnable
= dev
->enabled
;
202 if (config
->s0ix_enable
) {
203 params
->SlpS0WithGbeSupport
= 1;
204 params
->PchPmSlpS0VmRuntimeControl
= 0;
205 params
->PchPmSlpS0Vm070VSupport
= 0;
206 params
->PchPmSlpS0Vm075VSupport
= 0;
212 params
->PchHdaDspEnable
= config
->PchHdaDspEnable
;
213 params
->PchHdaIDispCodecDisconnect
= config
->PchHdaIDispCodecDisconnect
;
214 params
->PchHdaAudioLinkHda
= config
->PchHdaAudioLinkHda
;
215 params
->PchHdaAudioLinkDmic0
= config
->PchHdaAudioLinkDmic0
;
216 params
->PchHdaAudioLinkDmic1
= config
->PchHdaAudioLinkDmic1
;
217 params
->PchHdaAudioLinkSsp0
= config
->PchHdaAudioLinkSsp0
;
218 params
->PchHdaAudioLinkSsp1
= config
->PchHdaAudioLinkSsp1
;
219 params
->PchHdaAudioLinkSsp2
= config
->PchHdaAudioLinkSsp2
;
220 params
->PchHdaAudioLinkSndw1
= config
->PchHdaAudioLinkSndw1
;
221 params
->PchHdaAudioLinkSndw2
= config
->PchHdaAudioLinkSndw2
;
222 params
->PchHdaAudioLinkSndw3
= config
->PchHdaAudioLinkSndw3
;
223 params
->PchHdaAudioLinkSndw4
= config
->PchHdaAudioLinkSndw4
;
226 params
->DdiPortEdp
= config
->DdiPortEdp
;
228 /* HPD of DDI ports */
229 params
->DdiPortBHpd
= config
->DdiPortBHpd
;
230 params
->DdiPortCHpd
= config
->DdiPortCHpd
;
231 params
->DdiPortDHpd
= config
->DdiPortDHpd
;
232 params
->DdiPortFHpd
= config
->DdiPortFHpd
;
234 /* DDC of DDI ports */
235 params
->DdiPortBDdc
= config
->DdiPortBDdc
;
236 params
->DdiPortCDdc
= config
->DdiPortCDdc
;
237 params
->DdiPortDDdc
= config
->DdiPortDDdc
;
238 params
->DdiPortFDdc
= config
->DdiPortFDdc
;
241 params
->PchPmPcieWakeFromDeepSx
= config
->LanWakeFromDeepSx
;
242 params
->PchPmWolEnableOverride
= config
->WolEnableOverride
;
245 params
->PchPmSlpS0Enable
= config
->s0ix_enable
;
247 /* disable Legacy PME */
248 memset(params
->PcieRpPmSci
, 0, sizeof(params
->PcieRpPmSci
));
250 /* Legacy 8254 timer support */
251 params
->Enable8254ClockGating
= !CONFIG_USE_LEGACY_8254_TIMER
;
252 params
->Enable8254ClockGatingOnS3
= 1;
255 for (i
= 0; i
< ARRAY_SIZE(config
->usb2_ports
); i
++) {
256 params
->PortUsb20Enable
[i
] = config
->usb2_ports
[i
].enable
;
257 params
->Usb2OverCurrentPin
[i
] = config
->usb2_ports
[i
].ocpin
;
258 params
->Usb2AfePetxiset
[i
] = config
->usb2_ports
[i
].pre_emp_bias
;
259 params
->Usb2AfeTxiset
[i
] = config
->usb2_ports
[i
].tx_bias
;
260 params
->Usb2AfePredeemp
[i
] =
261 config
->usb2_ports
[i
].tx_emp_enable
;
262 params
->Usb2AfePehalfbit
[i
] = config
->usb2_ports
[i
].pre_emp_bit
;
265 for (i
= 0; i
< ARRAY_SIZE(config
->usb3_ports
); i
++) {
266 params
->PortUsb30Enable
[i
] = config
->usb3_ports
[i
].enable
;
267 params
->Usb3OverCurrentPin
[i
] = config
->usb3_ports
[i
].ocpin
;
268 if (config
->usb3_ports
[i
].tx_de_emp
) {
269 params
->Usb3HsioTxDeEmphEnable
[i
] = 1;
270 params
->Usb3HsioTxDeEmph
[i
] =
271 config
->usb3_ports
[i
].tx_de_emp
;
273 if (config
->usb3_ports
[i
].tx_downscale_amp
) {
274 params
->Usb3HsioTxDownscaleAmpEnable
[i
] = 1;
275 params
->Usb3HsioTxDownscaleAmp
[i
] =
276 config
->usb3_ports
[i
].tx_downscale_amp
;
280 /* Enable xDCI controller if enabled in devicetree and allowed */
281 dev
= pcidev_path_on_root(PCH_DEVFN_USBOTG
);
283 if (!xdci_can_enable())
285 params
->XdciEnable
= dev
->enabled
;
287 params
->XdciEnable
= 0;
289 /* Set Debug serial port */
290 params
->SerialIoDebugUartNumber
= CONFIG_UART_FOR_CONSOLE
;
291 #if !CONFIG(SOC_INTEL_COMETLAKE)
292 params
->SerialIoEnableDebugUartAfterPost
= CONFIG_INTEL_LPSS_UART_FOR_CONSOLE
;
295 /* Enable CNVi Wifi if enabled in device tree */
296 dev
= pcidev_path_on_root(PCH_DEVFN_CNViWIFI
);
297 #if CONFIG(SOC_INTEL_COMETLAKE)
299 params
->CnviMode
= dev
->enabled
;
301 params
->CnviMode
= 0;
304 params
->PchCnviMode
= dev
->enabled
;
306 params
->PchCnviMode
= 0;
309 for (i
= 0; i
< ARRAY_SIZE(config
->PcieClkSrcUsage
); i
++) {
310 if (config
->PcieClkSrcUsage
[i
] == 0)
311 config
->PcieClkSrcUsage
[i
] = PCIE_CLK_NOTUSED
;
313 memcpy(params
->PcieClkSrcUsage
, config
->PcieClkSrcUsage
,
314 sizeof(config
->PcieClkSrcUsage
));
315 memcpy(params
->PcieClkSrcClkReq
, config
->PcieClkSrcClkReq
,
316 sizeof(config
->PcieClkSrcClkReq
));
317 memcpy(params
->PcieRpLtrEnable
, config
->PcieRpLtrEnable
,
318 sizeof(config
->PcieRpLtrEnable
));
319 memcpy(params
->PcieRpHotPlug
, config
->PcieRpHotPlug
,
320 sizeof(config
->PcieRpHotPlug
));
323 dev
= pcidev_path_on_root(PCH_DEVFN_EMMC
);
325 params
->ScsEmmcEnabled
= 0;
327 params
->ScsEmmcEnabled
= dev
->enabled
;
328 params
->ScsEmmcHs400Enabled
= config
->ScsEmmcHs400Enabled
;
329 params
->PchScsEmmcHs400DllDataValid
= config
->EmmcHs400DllNeed
;
330 if (config
->EmmcHs400DllNeed
== 1) {
331 params
->PchScsEmmcHs400RxStrobeDll1
=
332 config
->EmmcHs400RxStrobeDll1
;
333 params
->PchScsEmmcHs400TxDataDll
=
334 config
->EmmcHs400TxDataDll
;
338 dev
= pcidev_path_on_root(PCH_DEVFN_SDCARD
);
340 params
->ScsSdCardEnabled
= 0;
342 params
->ScsSdCardEnabled
= dev
->enabled
;
343 params
->SdCardPowerEnableActiveHigh
=
344 CONFIG(MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE
);
345 #if CONFIG(SOC_INTEL_COMETLAKE)
346 params
->ScsSdCardWpPinEnabled
= config
->ScsSdCardWpPinEnabled
;
350 dev
= pcidev_path_on_root(PCH_DEVFN_UFS
);
352 params
->ScsUfsEnabled
= 0;
354 params
->ScsUfsEnabled
= dev
->enabled
;
356 params
->Heci3Enabled
= config
->Heci3Enabled
;
357 #if !CONFIG(HECI_DISABLE_USING_SMM)
358 params
->Heci1Disabled
= !config
->HeciEnabled
;
360 params
->Device4Enable
= config
->Device4Enable
;
362 /* VrConfig Settings for 5 domains
363 * 0 = System Agent, 1 = IA Core, 2 = Ring,
364 * 3 = GT unsliced, 4 = GT sliced */
365 for (i
= 0; i
< ARRAY_SIZE(config
->domain_vr_config
); i
++)
366 fill_vr_domain_config(params
, i
, &config
->domain_vr_config
[i
]);
368 /* Acoustic Noise Mitigation */
369 params
->AcousticNoiseMitigation
= config
->AcousticNoiseMitigation
;
370 params
->SlowSlewRateForIa
= config
->SlowSlewRateForIa
;
371 params
->SlowSlewRateForGt
= config
->SlowSlewRateForGt
;
372 params
->SlowSlewRateForSa
= config
->SlowSlewRateForSa
;
373 params
->SlowSlewRateForFivr
= config
->SlowSlewRateForFivr
;
374 params
->FastPkgCRampDisableIa
= config
->FastPkgCRampDisableIa
;
375 params
->FastPkgCRampDisableGt
= config
->FastPkgCRampDisableGt
;
376 params
->FastPkgCRampDisableSa
= config
->FastPkgCRampDisableSa
;
377 params
->FastPkgCRampDisableFivr
= config
->FastPkgCRampDisableFivr
;
379 /* Power Optimizer */
380 params
->SataPwrOptEnable
= config
->satapwroptimize
;
382 /* Disable PCH ACPI timer */
383 params
->EnableTcoTimer
= !config
->PmTimerDisabled
;
385 /* Apply minimum assertion width settings if non-zero */
386 if (config
->PchPmSlpS3MinAssert
)
387 params
->PchPmSlpS3MinAssert
= config
->PchPmSlpS3MinAssert
;
388 if (config
->PchPmSlpS4MinAssert
)
389 params
->PchPmSlpS4MinAssert
= config
->PchPmSlpS4MinAssert
;
390 if (config
->PchPmSlpSusMinAssert
)
391 params
->PchPmSlpSusMinAssert
= config
->PchPmSlpSusMinAssert
;
392 if (config
->PchPmSlpAMinAssert
)
393 params
->PchPmSlpAMinAssert
= config
->PchPmSlpAMinAssert
;
395 /* Set TccActivationOffset */
396 tconfig
->TccActivationOffset
= config
->tcc_offset
;
398 /* Unlock all GPIO pads */
399 tconfig
->PchUnlockGpioPads
= config
->PchUnlockGpioPads
;
402 * GSPI Chip Select parameters
403 * The GSPI driver assumes that CS0 is the used chip-select line,
404 * therefore only CS0 is configured below.
406 #if CONFIG(SOC_INTEL_COMETLAKE)
407 configure_gspi_cs(0, config
, ¶ms
->SerialIoSpi0CsPolarity
[0],
408 ¶ms
->SerialIoSpi0CsEnable
[0],
409 ¶ms
->SerialIoSpiDefaultCsOutput
[0]);
410 configure_gspi_cs(1, config
, ¶ms
->SerialIoSpi1CsPolarity
[0],
411 ¶ms
->SerialIoSpi1CsEnable
[0],
412 ¶ms
->SerialIoSpiDefaultCsOutput
[1]);
413 configure_gspi_cs(2, config
, ¶ms
->SerialIoSpi2CsPolarity
[0],
414 ¶ms
->SerialIoSpi2CsEnable
[0],
415 ¶ms
->SerialIoSpiDefaultCsOutput
[2]);
417 for (i
= 0; i
< CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX
; i
++)
418 configure_gspi_cs(i
, config
,
419 ¶ms
->SerialIoSpiCsPolarity
[0], NULL
, NULL
);
422 /* Chipset Lockdown */
423 if (get_lockdown_config() == CHIPSET_LOCKDOWN_COREBOOT
) {
424 tconfig
->PchLockDownGlobalSmi
= 0;
425 tconfig
->PchLockDownBiosInterface
= 0;
426 params
->PchLockDownBiosLock
= 0;
427 params
->PchLockDownRtcMemoryLock
= 0;
428 #if CONFIG(SOC_INTEL_COMETLAKE)
430 * Skip SPI Flash Lockdown from inside FSP.
431 * Making this config "0" means FSP won't set the FLOCKDN bit
432 * of SPIBAR + 0x04 (i.e., Bit 15 of BIOS_HSFSTS_CTL).
433 * So, it becomes coreboot's responsibility to set this bit
434 * before end of POST for security concerns.
436 params
->SpiFlashCfgLockDown
= 0;
439 tconfig
->PchLockDownGlobalSmi
= 1;
440 tconfig
->PchLockDownBiosInterface
= 1;
441 params
->PchLockDownBiosLock
= 1;
442 params
->PchLockDownRtcMemoryLock
= 1;
443 #if CONFIG(SOC_INTEL_COMETLAKE)
445 * Enable SPI Flash Lockdown from inside FSP.
446 * Making this config "1" means FSP will set the FLOCKDN bit
447 * of SPIBAR + 0x04 (i.e., Bit 15 of BIOS_HSFSTS_CTL).
449 params
->SpiFlashCfgLockDown
= 1;
454 /* Mainboard GPIO Configuration */
455 __weak
void mainboard_silicon_init_params(FSP_S_CONFIG
*params
)
457 printk(BIOS_DEBUG
, "WEAK: %s/%s called\n", __FILE__
, __func__
);
460 /* Return list of SOC LPSS controllers */
461 const pci_devfn_t
*soc_lpss_controllers_list(size_t *size
)
463 *size
= ARRAY_SIZE(serial_io_dev
);
464 return serial_io_dev
;