coreboot-kgpe-d16/src/mainboard/google/volteer/mainboard.c

180 lines
5.2 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <acpi/acpi.h>
#include <baseboard/variants.h>
#include <device/device.h>
mainboard/google/volteer: Disable S0i3.4 if cr50 firmware is too old For Volteer (and future Tiger Lake boards) we can enable mode S0i3.4 only if we know that the Cr50 is generating 100us interrupt pulses. We have to do so, because the SoC is not guaranteed to detect pulses shorter than 100us in S0i3.4 substate. A new Kconfig setting CR50_USE_LONG_INTERRUPT_PULSES controls new code running in verstage, which will program a new Cr50 register, provided that Cr50 firmware is new enough to support the register. This CL adds code to detect the case when Cr50 is unable to generate longer pulses, and in that case explicitly disable the S0i3.4 substate as well as setting gpio_pm_override to all zeroes. This will increase power usage slightly, but guarantee that the GPIO block in the SoC does not switch to a slower sampling clock. In practice, this case will only be encountered in the factory, before the Cr50 chip is updated to a new RW image. (Prior to this change, the gpio_pm_override was hardcoded to zero for Volteer, but the S0i3.4 substate was not disabled. According to my conversations with Intel engineers, that was not enough to guarantee detection pulses shorter than 100us. But it is entirely possible that we have just been "lucky" that the SoC has not gone into low power mode during the boot process, where most of the cr50 communication happens.) TEST=util/abuild/abuild -t GOOGLE_VOLTEER -c max -x BUG=b:154333137 Change-Id: Idef1fffd410a345678da4b3c8aea46ac74a01470 Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44359 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
2020-08-28 22:44:21 +02:00
#include <drivers/spi/tpm/tpm.h>
#include <ec/ec.h>
#include <fw_config.h>
#include <gpio.h>
#include <intelblocks/gpio.h>
mainboard/google/volteer: Disable S0i3.4 if cr50 firmware is too old For Volteer (and future Tiger Lake boards) we can enable mode S0i3.4 only if we know that the Cr50 is generating 100us interrupt pulses. We have to do so, because the SoC is not guaranteed to detect pulses shorter than 100us in S0i3.4 substate. A new Kconfig setting CR50_USE_LONG_INTERRUPT_PULSES controls new code running in verstage, which will program a new Cr50 register, provided that Cr50 firmware is new enough to support the register. This CL adds code to detect the case when Cr50 is unable to generate longer pulses, and in that case explicitly disable the S0i3.4 substate as well as setting gpio_pm_override to all zeroes. This will increase power usage slightly, but guarantee that the GPIO block in the SoC does not switch to a slower sampling clock. In practice, this case will only be encountered in the factory, before the Cr50 chip is updated to a new RW image. (Prior to this change, the gpio_pm_override was hardcoded to zero for Volteer, but the S0i3.4 substate was not disabled. According to my conversations with Intel engineers, that was not enough to guarantee detection pulses shorter than 100us. But it is entirely possible that we have just been "lucky" that the SoC has not gone into low power mode during the boot process, where most of the cr50 communication happens.) TEST=util/abuild/abuild -t GOOGLE_VOLTEER -c max -x BUG=b:154333137 Change-Id: Idef1fffd410a345678da4b3c8aea46ac74a01470 Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44359 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
2020-08-28 22:44:21 +02:00
#include <security/tpm/tss.h>
#include <soc/gpio.h>
#include <soc/pci_devs.h>
mainboard/google/volteer: Disable S0i3.4 if cr50 firmware is too old For Volteer (and future Tiger Lake boards) we can enable mode S0i3.4 only if we know that the Cr50 is generating 100us interrupt pulses. We have to do so, because the SoC is not guaranteed to detect pulses shorter than 100us in S0i3.4 substate. A new Kconfig setting CR50_USE_LONG_INTERRUPT_PULSES controls new code running in verstage, which will program a new Cr50 register, provided that Cr50 firmware is new enough to support the register. This CL adds code to detect the case when Cr50 is unable to generate longer pulses, and in that case explicitly disable the S0i3.4 substate as well as setting gpio_pm_override to all zeroes. This will increase power usage slightly, but guarantee that the GPIO block in the SoC does not switch to a slower sampling clock. In practice, this case will only be encountered in the factory, before the Cr50 chip is updated to a new RW image. (Prior to this change, the gpio_pm_override was hardcoded to zero for Volteer, but the S0i3.4 substate was not disabled. According to my conversations with Intel engineers, that was not enough to guarantee detection pulses shorter than 100us. But it is entirely possible that we have just been "lucky" that the SoC has not gone into low power mode during the boot process, where most of the cr50 communication happens.) TEST=util/abuild/abuild -t GOOGLE_VOLTEER -c max -x BUG=b:154333137 Change-Id: Idef1fffd410a345678da4b3c8aea46ac74a01470 Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44359 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
2020-08-28 22:44:21 +02:00
#include <soc/ramstage.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <variant/gpio.h>
#include <vb2_api.h>
#include "drivers/intel/pmc_mux/conn/chip.h"
extern struct chip_operations drivers_intel_pmc_mux_conn_ops;
static bool is_port1(struct device *dev)
{
return dev->path.type == DEVICE_PATH_GENERIC && dev->path.generic.id == 1 &&
dev->chip_ops == &drivers_intel_pmc_mux_conn_ops;
}
static void typec_orientation_fixup(void)
{
/*
* TODO: This is an ugly hack, see if there's a better way to accomplish this same thing
* via fw_config + devicetree, i.e., change a register's value depending on fw_config
* probing.
*/
const struct device *pmc;
const struct device *mux;
const struct device *conn;
pmc = pcidev_path_on_root(PCH_DEVFN_PMC);
if (!pmc || !pmc->link_list->children) {
printk(BIOS_ERR, "%s: unable to find PMC device or its mux\n", __func__);
return;
}
/*
* Find port 1 underneath PMC.MUX; some variants may not have this defined, so it's okay
* to just silently return here.
*/
mux = pmc->link_list->children;
conn = dev_find_matching_device_on_bus(mux->link_list, is_port1);
if (!conn)
return;
if (fw_config_probe(FW_CONFIG(DB_USB, USB4_GEN2)) ||
fw_config_probe(FW_CONFIG(DB_USB, USB3_ACTIVE)) ||
fw_config_probe(FW_CONFIG(DB_USB, USB4_GEN3)) ||
fw_config_probe(FW_CONFIG(DB_USB, USB3_NO_A))) {
struct drivers_intel_pmc_mux_conn_config *config = conn->chip_info;
if (config) {
printk(BIOS_INFO, "Configure Right Type-C port orientation for retimer\n");
config->sbu_orientation = TYPEC_ORIENTATION_NORMAL;
}
}
}
static void mainboard_init(struct device *dev)
{
mainboard_ec_init();
typec_orientation_fixup();
}
static void add_fw_config_oem_string(const struct fw_config *config, void *arg)
{
struct smbios_type11 *t;
char buffer[64];
t = (struct smbios_type11 *)arg;
snprintf(buffer, sizeof(buffer), "%s-%s", config->field_name, config->option_name);
t->count = smbios_add_string(t->eos, buffer);
}
static void mainboard_smbios_strings(struct device *dev, struct smbios_type11 *t)
{
fw_config_for_each_found(add_fw_config_oem_string, t);
}
static void mainboard_enable(struct device *dev)
{
dev->ops->init = mainboard_init;
dev->ops->acpi_inject_dsdt = chromeos_dsdt_generator;
dev->ops->get_smbios_strings = mainboard_smbios_strings;
}
mainboard/google/volteer: Disable S0i3.4 if cr50 firmware is too old For Volteer (and future Tiger Lake boards) we can enable mode S0i3.4 only if we know that the Cr50 is generating 100us interrupt pulses. We have to do so, because the SoC is not guaranteed to detect pulses shorter than 100us in S0i3.4 substate. A new Kconfig setting CR50_USE_LONG_INTERRUPT_PULSES controls new code running in verstage, which will program a new Cr50 register, provided that Cr50 firmware is new enough to support the register. This CL adds code to detect the case when Cr50 is unable to generate longer pulses, and in that case explicitly disable the S0i3.4 substate as well as setting gpio_pm_override to all zeroes. This will increase power usage slightly, but guarantee that the GPIO block in the SoC does not switch to a slower sampling clock. In practice, this case will only be encountered in the factory, before the Cr50 chip is updated to a new RW image. (Prior to this change, the gpio_pm_override was hardcoded to zero for Volteer, but the S0i3.4 substate was not disabled. According to my conversations with Intel engineers, that was not enough to guarantee detection pulses shorter than 100us. But it is entirely possible that we have just been "lucky" that the SoC has not gone into low power mode during the boot process, where most of the cr50 communication happens.) TEST=util/abuild/abuild -t GOOGLE_VOLTEER -c max -x BUG=b:154333137 Change-Id: Idef1fffd410a345678da4b3c8aea46ac74a01470 Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44359 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
2020-08-28 22:44:21 +02:00
void mainboard_update_soc_chip_config(struct soc_intel_tigerlake_config *cfg)
{
int ret;
if (!CONFIG(MAINBOARD_HAS_SPI_TPM_CR50)) {
/*
* Negotiation of long interrupt pulses is only supported via SPI. I2C is only
* used on reworked prototypes on which the TPM is replaced with Dauntless under
* development, it will use long pulses by default, or use the interrupt line in
* a different way altogether.
*/
return;
}
ret = tlcl_lib_init();
if (ret != VB2_SUCCESS) {
printk(BIOS_ERR, "tlcl_lib_init() failed: 0x%x\n", ret);
return;
}
if (cr50_is_long_interrupt_pulse_enabled()) {
mainboard/google/volteer: Disable S0i3.4 if cr50 firmware is too old For Volteer (and future Tiger Lake boards) we can enable mode S0i3.4 only if we know that the Cr50 is generating 100us interrupt pulses. We have to do so, because the SoC is not guaranteed to detect pulses shorter than 100us in S0i3.4 substate. A new Kconfig setting CR50_USE_LONG_INTERRUPT_PULSES controls new code running in verstage, which will program a new Cr50 register, provided that Cr50 firmware is new enough to support the register. This CL adds code to detect the case when Cr50 is unable to generate longer pulses, and in that case explicitly disable the S0i3.4 substate as well as setting gpio_pm_override to all zeroes. This will increase power usage slightly, but guarantee that the GPIO block in the SoC does not switch to a slower sampling clock. In practice, this case will only be encountered in the factory, before the Cr50 chip is updated to a new RW image. (Prior to this change, the gpio_pm_override was hardcoded to zero for Volteer, but the S0i3.4 substate was not disabled. According to my conversations with Intel engineers, that was not enough to guarantee detection pulses shorter than 100us. But it is entirely possible that we have just been "lucky" that the SoC has not gone into low power mode during the boot process, where most of the cr50 communication happens.) TEST=util/abuild/abuild -t GOOGLE_VOLTEER -c max -x BUG=b:154333137 Change-Id: Idef1fffd410a345678da4b3c8aea46ac74a01470 Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44359 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
2020-08-28 22:44:21 +02:00
printk(BIOS_INFO, "Enabling S0i3.4\n");
} else {
/*
* Disable S0i3.4, preventing the GPIO block from switching to
* slow clock.
*/
printk(BIOS_INFO, "Not enabling S0i3.4\n");
cfg->LpmStateDisableMask |= LPM_S0i3_4;
cfg->gpio_override_pm = 1;
memset(cfg->gpio_pm, 0, sizeof(cfg->gpio_pm));
}
}
static void mainboard_chip_init(void *chip_info)
{
const struct pad_config *base_pads;
const struct pad_config *override_pads;
size_t base_num, override_num;
base_pads = variant_base_gpio_table(&base_num);
override_pads = variant_override_gpio_table(&override_num);
gpio_configure_pads_with_override(base_pads, base_num, override_pads, override_num);
/*
* Check SATAXPCIE1 (GPP_A12) RX status to determine if SSD is NVMe or SATA and set
* the IOSSTATE RX field to drive 0 or 1 back to the internal controller to ensure
* the attached device is not mis-detected on resume from S0ix.
*/
if (gpio_get(GPP_A12)) {
const struct pad_config gpio_pedet_nvme[] = {
PAD_CFG_NF_IOSSTATE(GPP_A12, NONE, DEEP, NF1, HIZCRx1),
};
gpio_configure_pads(gpio_pedet_nvme, ARRAY_SIZE(gpio_pedet_nvme));
printk(BIOS_INFO, "SATAXPCIE1 indicates PCIe NVMe is present\n");
} else {
const struct pad_config gpio_pedet_sata[] = {
PAD_CFG_NF_IOSSTATE(GPP_A12, NONE, DEEP, NF1, HIZCRx0),
};
gpio_configure_pads(gpio_pedet_sata, ARRAY_SIZE(gpio_pedet_sata));
printk(BIOS_INFO, "SATAXPCIE1 indicates SATA SSD is present\n");
}
}
void mainboard_silicon_init_params(FSP_S_CONFIG *params)
{
bool has_usb4;
/* If device doesn't have USB4 hardware, disable tbt */
has_usb4 = (fw_config_probe(FW_CONFIG(DB_USB, USB4_GEN2))
|| fw_config_probe(FW_CONFIG(DB_USB, USB4_GEN3)));
if (!has_usb4)
memset(params->ITbtPcieRootPortEn, 0,
ARRAY_SIZE(params->ITbtPcieRootPortEn)
* sizeof(*params->ITbtPcieRootPortEn));
}
struct chip_operations mainboard_ops = {
.init = mainboard_chip_init,
.enable_dev = mainboard_enable,
};