2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * 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
));
195 params
->SlpS0WithGbeSupport
= 0;
196 params
->PchPmSlpS0VmRuntimeControl
= config
->PchPmSlpS0VmRuntimeControl
;
197 params
->PchPmSlpS0Vm070VSupport
= config
->PchPmSlpS0Vm070VSupport
;
198 params
->PchPmSlpS0Vm075VSupport
= config
->PchPmSlpS0Vm075VSupport
;
201 dev
= pcidev_path_on_root(PCH_DEVFN_GBE
);
203 params
->PchLanEnable
= 0;
205 params
->PchLanEnable
= dev
->enabled
;
206 if (config
->s0ix_enable
&& params
->PchLanEnable
) {
208 * The VmControl UPDs need to be set as per board
209 * design to allow voltage margining in S0ix to lower
211 * But if GbE is enabled, voltage magining cannot be
212 * enabled, so the Vm control UPDs need to be set to 0.
214 params
->SlpS0WithGbeSupport
= 1;
215 params
->PchPmSlpS0VmRuntimeControl
= 0;
216 params
->PchPmSlpS0Vm070VSupport
= 0;
217 params
->PchPmSlpS0Vm075VSupport
= 0;
223 params
->PchHdaDspEnable
= config
->PchHdaDspEnable
;
224 params
->PchHdaIDispCodecDisconnect
= config
->PchHdaIDispCodecDisconnect
;
225 params
->PchHdaAudioLinkHda
= config
->PchHdaAudioLinkHda
;
226 params
->PchHdaAudioLinkDmic0
= config
->PchHdaAudioLinkDmic0
;
227 params
->PchHdaAudioLinkDmic1
= config
->PchHdaAudioLinkDmic1
;
228 params
->PchHdaAudioLinkSsp0
= config
->PchHdaAudioLinkSsp0
;
229 params
->PchHdaAudioLinkSsp1
= config
->PchHdaAudioLinkSsp1
;
230 params
->PchHdaAudioLinkSsp2
= config
->PchHdaAudioLinkSsp2
;
231 params
->PchHdaAudioLinkSndw1
= config
->PchHdaAudioLinkSndw1
;
232 params
->PchHdaAudioLinkSndw2
= config
->PchHdaAudioLinkSndw2
;
233 params
->PchHdaAudioLinkSndw3
= config
->PchHdaAudioLinkSndw3
;
234 params
->PchHdaAudioLinkSndw4
= config
->PchHdaAudioLinkSndw4
;
237 params
->DdiPortEdp
= config
->DdiPortEdp
;
239 /* HPD of DDI ports */
240 params
->DdiPortBHpd
= config
->DdiPortBHpd
;
241 params
->DdiPortCHpd
= config
->DdiPortCHpd
;
242 params
->DdiPortDHpd
= config
->DdiPortDHpd
;
243 params
->DdiPortFHpd
= config
->DdiPortFHpd
;
245 /* DDC of DDI ports */
246 params
->DdiPortBDdc
= config
->DdiPortBDdc
;
247 params
->DdiPortCDdc
= config
->DdiPortCDdc
;
248 params
->DdiPortDDdc
= config
->DdiPortDDdc
;
249 params
->DdiPortFDdc
= config
->DdiPortFDdc
;
252 params
->PchPmPcieWakeFromDeepSx
= config
->LanWakeFromDeepSx
;
253 params
->PchPmWolEnableOverride
= config
->WolEnableOverride
;
256 params
->PchPmSlpS0Enable
= config
->s0ix_enable
;
258 /* disable Legacy PME */
259 memset(params
->PcieRpPmSci
, 0, sizeof(params
->PcieRpPmSci
));
261 /* Legacy 8254 timer support */
262 params
->Enable8254ClockGating
= !CONFIG_USE_LEGACY_8254_TIMER
;
263 params
->Enable8254ClockGatingOnS3
= !CONFIG_USE_LEGACY_8254_TIMER
;
266 for (i
= 0; i
< ARRAY_SIZE(config
->usb2_ports
); i
++) {
267 params
->PortUsb20Enable
[i
] = config
->usb2_ports
[i
].enable
;
268 params
->Usb2OverCurrentPin
[i
] = config
->usb2_ports
[i
].ocpin
;
269 params
->Usb2AfePetxiset
[i
] = config
->usb2_ports
[i
].pre_emp_bias
;
270 params
->Usb2AfeTxiset
[i
] = config
->usb2_ports
[i
].tx_bias
;
271 params
->Usb2AfePredeemp
[i
] =
272 config
->usb2_ports
[i
].tx_emp_enable
;
273 params
->Usb2AfePehalfbit
[i
] = config
->usb2_ports
[i
].pre_emp_bit
;
276 if (config
->PchUsb2PhySusPgDisable
)
277 params
->PchUsb2PhySusPgEnable
= 0;
279 for (i
= 0; i
< ARRAY_SIZE(config
->usb3_ports
); i
++) {
280 params
->PortUsb30Enable
[i
] = config
->usb3_ports
[i
].enable
;
281 params
->Usb3OverCurrentPin
[i
] = config
->usb3_ports
[i
].ocpin
;
282 if (config
->usb3_ports
[i
].tx_de_emp
) {
283 params
->Usb3HsioTxDeEmphEnable
[i
] = 1;
284 params
->Usb3HsioTxDeEmph
[i
] =
285 config
->usb3_ports
[i
].tx_de_emp
;
287 if (config
->usb3_ports
[i
].tx_downscale_amp
) {
288 params
->Usb3HsioTxDownscaleAmpEnable
[i
] = 1;
289 params
->Usb3HsioTxDownscaleAmp
[i
] =
290 config
->usb3_ports
[i
].tx_downscale_amp
;
294 /* Enable xDCI controller if enabled in devicetree and allowed */
295 dev
= pcidev_path_on_root(PCH_DEVFN_USBOTG
);
297 if (!xdci_can_enable())
299 params
->XdciEnable
= dev
->enabled
;
301 params
->XdciEnable
= 0;
303 /* Set Debug serial port */
304 params
->SerialIoDebugUartNumber
= CONFIG_UART_FOR_CONSOLE
;
305 #if !CONFIG(SOC_INTEL_COMETLAKE)
306 params
->SerialIoEnableDebugUartAfterPost
= CONFIG_INTEL_LPSS_UART_FOR_CONSOLE
;
309 /* Enable CNVi Wifi if enabled in device tree */
310 dev
= pcidev_path_on_root(PCH_DEVFN_CNViWIFI
);
311 #if CONFIG(SOC_INTEL_COMETLAKE)
313 params
->CnviMode
= dev
->enabled
;
315 params
->CnviMode
= 0;
318 params
->PchCnviMode
= dev
->enabled
;
320 params
->PchCnviMode
= 0;
323 for (i
= 0; i
< ARRAY_SIZE(config
->PcieClkSrcUsage
); i
++) {
324 if (config
->PcieClkSrcUsage
[i
] == 0)
325 config
->PcieClkSrcUsage
[i
] = PCIE_CLK_NOTUSED
;
327 memcpy(params
->PcieClkSrcUsage
, config
->PcieClkSrcUsage
,
328 sizeof(config
->PcieClkSrcUsage
));
329 memcpy(params
->PcieClkSrcClkReq
, config
->PcieClkSrcClkReq
,
330 sizeof(config
->PcieClkSrcClkReq
));
331 memcpy(params
->PcieRpLtrEnable
, config
->PcieRpLtrEnable
,
332 sizeof(config
->PcieRpLtrEnable
));
333 memcpy(params
->PcieRpHotPlug
, config
->PcieRpHotPlug
,
334 sizeof(config
->PcieRpHotPlug
));
337 dev
= pcidev_path_on_root(PCH_DEVFN_EMMC
);
339 params
->ScsEmmcEnabled
= 0;
341 params
->ScsEmmcEnabled
= dev
->enabled
;
342 params
->ScsEmmcHs400Enabled
= config
->ScsEmmcHs400Enabled
;
343 params
->PchScsEmmcHs400DllDataValid
= config
->EmmcHs400DllNeed
;
344 if (config
->EmmcHs400DllNeed
== 1) {
345 params
->PchScsEmmcHs400RxStrobeDll1
=
346 config
->EmmcHs400RxStrobeDll1
;
347 params
->PchScsEmmcHs400TxDataDll
=
348 config
->EmmcHs400TxDataDll
;
352 dev
= pcidev_path_on_root(PCH_DEVFN_SDCARD
);
354 params
->ScsSdCardEnabled
= 0;
356 params
->ScsSdCardEnabled
= dev
->enabled
;
357 params
->SdCardPowerEnableActiveHigh
=
358 CONFIG(MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE
);
359 #if CONFIG(SOC_INTEL_COMETLAKE)
360 params
->ScsSdCardWpPinEnabled
= config
->ScsSdCardWpPinEnabled
;
364 dev
= pcidev_path_on_root(PCH_DEVFN_UFS
);
366 params
->ScsUfsEnabled
= 0;
368 params
->ScsUfsEnabled
= dev
->enabled
;
370 params
->Heci3Enabled
= config
->Heci3Enabled
;
371 #if !CONFIG(HECI_DISABLE_USING_SMM)
372 params
->Heci1Disabled
= !config
->HeciEnabled
;
374 params
->Device4Enable
= config
->Device4Enable
;
376 /* Teton Glacier hybrid storage support */
377 params
->TetonGlacierMode
= config
->TetonGlacierMode
;
379 /* VrConfig Settings for 5 domains
380 * 0 = System Agent, 1 = IA Core, 2 = Ring,
381 * 3 = GT unsliced, 4 = GT sliced */
382 for (i
= 0; i
< ARRAY_SIZE(config
->domain_vr_config
); i
++)
383 fill_vr_domain_config(params
, i
, &config
->domain_vr_config
[i
]);
385 /* Acoustic Noise Mitigation */
386 params
->AcousticNoiseMitigation
= config
->AcousticNoiseMitigation
;
387 params
->SlowSlewRateForIa
= config
->SlowSlewRateForIa
;
388 params
->SlowSlewRateForGt
= config
->SlowSlewRateForGt
;
389 params
->SlowSlewRateForSa
= config
->SlowSlewRateForSa
;
390 params
->SlowSlewRateForFivr
= config
->SlowSlewRateForFivr
;
391 params
->FastPkgCRampDisableIa
= config
->FastPkgCRampDisableIa
;
392 params
->FastPkgCRampDisableGt
= config
->FastPkgCRampDisableGt
;
393 params
->FastPkgCRampDisableSa
= config
->FastPkgCRampDisableSa
;
394 params
->FastPkgCRampDisableFivr
= config
->FastPkgCRampDisableFivr
;
396 /* Power Optimizer */
397 params
->SataPwrOptEnable
= config
->satapwroptimize
;
399 /* Disable PCH ACPI timer */
400 params
->EnableTcoTimer
= !config
->PmTimerDisabled
;
402 /* Apply minimum assertion width settings if non-zero */
403 if (config
->PchPmSlpS3MinAssert
)
404 params
->PchPmSlpS3MinAssert
= config
->PchPmSlpS3MinAssert
;
405 if (config
->PchPmSlpS4MinAssert
)
406 params
->PchPmSlpS4MinAssert
= config
->PchPmSlpS4MinAssert
;
407 if (config
->PchPmSlpSusMinAssert
)
408 params
->PchPmSlpSusMinAssert
= config
->PchPmSlpSusMinAssert
;
409 if (config
->PchPmSlpAMinAssert
)
410 params
->PchPmSlpAMinAssert
= config
->PchPmSlpAMinAssert
;
412 /* Set TccActivationOffset */
413 tconfig
->TccActivationOffset
= config
->tcc_offset
;
415 /* Unlock all GPIO pads */
416 tconfig
->PchUnlockGpioPads
= config
->PchUnlockGpioPads
;
418 /* Set correct Sirq mode based on config */
419 params
->PchSirqEnable
= config
->serirq_mode
!= SERIRQ_OFF
;
420 params
->PchSirqMode
= config
->serirq_mode
== SERIRQ_CONTINUOUS
;
423 * GSPI Chip Select parameters
424 * The GSPI driver assumes that CS0 is the used chip-select line,
425 * therefore only CS0 is configured below.
427 #if CONFIG(SOC_INTEL_COMETLAKE)
428 configure_gspi_cs(0, config
, ¶ms
->SerialIoSpi0CsPolarity
[0],
429 ¶ms
->SerialIoSpi0CsEnable
[0],
430 ¶ms
->SerialIoSpiDefaultCsOutput
[0]);
431 configure_gspi_cs(1, config
, ¶ms
->SerialIoSpi1CsPolarity
[0],
432 ¶ms
->SerialIoSpi1CsEnable
[0],
433 ¶ms
->SerialIoSpiDefaultCsOutput
[1]);
434 configure_gspi_cs(2, config
, ¶ms
->SerialIoSpi2CsPolarity
[0],
435 ¶ms
->SerialIoSpi2CsEnable
[0],
436 ¶ms
->SerialIoSpiDefaultCsOutput
[2]);
438 for (i
= 0; i
< CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX
; i
++)
439 configure_gspi_cs(i
, config
,
440 ¶ms
->SerialIoSpiCsPolarity
[0], NULL
, NULL
);
443 /* Chipset Lockdown */
444 if (get_lockdown_config() == CHIPSET_LOCKDOWN_COREBOOT
) {
445 tconfig
->PchLockDownGlobalSmi
= 0;
446 tconfig
->PchLockDownBiosInterface
= 0;
447 params
->PchLockDownBiosLock
= 0;
448 params
->PchLockDownRtcMemoryLock
= 0;
449 #if CONFIG(SOC_INTEL_COMETLAKE)
451 * Skip SPI Flash Lockdown from inside FSP.
452 * Making this config "0" means FSP won't set the FLOCKDN bit
453 * of SPIBAR + 0x04 (i.e., Bit 15 of BIOS_HSFSTS_CTL).
454 * So, it becomes coreboot's responsibility to set this bit
455 * before end of POST for security concerns.
457 params
->SpiFlashCfgLockDown
= 0;
460 tconfig
->PchLockDownGlobalSmi
= 1;
461 tconfig
->PchLockDownBiosInterface
= 1;
462 params
->PchLockDownBiosLock
= 1;
463 params
->PchLockDownRtcMemoryLock
= 1;
464 #if CONFIG(SOC_INTEL_COMETLAKE)
466 * Enable SPI Flash Lockdown from inside FSP.
467 * Making this config "1" means FSP will set the FLOCKDN bit
468 * of SPIBAR + 0x04 (i.e., Bit 15 of BIOS_HSFSTS_CTL).
470 params
->SpiFlashCfgLockDown
= 1;
474 dev
= pcidev_path_on_root(SA_DEVFN_IGD
);
475 if (CONFIG(RUN_FSP_GOP
) && dev
&& dev
->enabled
)
476 params
->PeiGraphicsPeimInit
= 1;
478 params
->PeiGraphicsPeimInit
= 0;
481 /* Mainboard GPIO Configuration */
482 __weak
void mainboard_silicon_init_params(FSP_S_CONFIG
*params
)
484 printk(BIOS_DEBUG
, "WEAK: %s/%s called\n", __FILE__
, __func__
);
487 /* Return list of SOC LPSS controllers */
488 const pci_devfn_t
*soc_lpss_controllers_list(size_t *size
)
490 *size
= ARRAY_SIZE(serial_io_dev
);
491 return serial_io_dev
;
494 /* Handle FSP logo params */
495 const struct cbmem_entry
*soc_load_logo(FSPS_UPD
*supd
)
497 return fsp_load_logo(&supd
->FspsConfig
.LogoPtr
, &supd
->FspsConfig
.LogoSize
);