soc/intel/alderlake: Add support to update descriptor at runtime

On nereid, we need to update the descriptor based on fw_config (see
the follow-up patch), so add support to update the descriptor at
runtime. This is a temporary workaround while we find a better solution.

This is basically adding back the configure_pmc_descriptor() function
removed in CB:63339, just making it generic and allowing it to update
multiple bytes at once.

BUG=b:226848617
TEST=With the following patch, Type-C and HDMI work on nereid.

Change-Id: I43c4d2888706561e42ff6b8ce0377eedbc38dbfe
Signed-off-by: Reka Norman <rekanorman@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/63365
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
Reviewed-by: Sam McNally <sammc@google.com>
This commit is contained in:
Reka Norman 2022-04-06 20:33:54 +10:00 committed by Patrick Georgi
parent d7cdeee74d
commit e790f929bd
4 changed files with 107 additions and 0 deletions

View File

@ -112,6 +112,13 @@ config CPU_SPECIFIC_OPTIONS
select UDK_202005_BINDING
select USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM
config ALDERLAKE_CONFIGURE_DESCRIPTOR
bool
help
Select this if the descriptor needs to be updated at runtime. This
can only be done if the descriptor region is writable, and should only
be used as a temporary workaround.
config ALDERLAKE_CAR_ENHANCED_NEM
bool
default y if !INTEL_CAR_NEM

View File

@ -16,6 +16,7 @@ bootblock-y += bootblock/report_platform.c
bootblock-y += espi.c
bootblock-y += gpio.c
bootblock-y += p2sb.c
bootblock-$(CONFIG_ALDERLAKE_CONFIGURE_DESCRIPTOR) += bootblock/update_descriptor.c
romstage-y += espi.c
romstage-y += gpio.c

View File

@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <arch/cpu.h>
#include <arch/mmio.h>
#include <cf9_reset.h>
#include <commonlib/region.h>
#include <console/console.h>
#include <cpu/intel/cpu_ids.h>
#include <fmap.h>
#include <intelblocks/pmclib.h>
#include <soc/bootblock.h>
#include <types.h>
/* Flash Master 1 : HOST/BIOS */
#define FLMSTR1 0x80
/* Flash signature Offset */
#define FLASH_SIGN_OFFSET 0x10
#define FLMSTR_WR_SHIFT_V2 20
#define FLASH_VAL_SIGN 0xFF0A55A
/* It checks whether host (Flash Master 1) has write access to the Descriptor Region or not */
static bool is_descriptor_writeable(uint8_t *desc)
{
/* Check flash has valid signature */
if (read32((void *)(desc + FLASH_SIGN_OFFSET)) != FLASH_VAL_SIGN) {
printk(BIOS_ERR, "Flash Descriptor is not valid\n");
return 0;
}
/* Check host has write access to the Descriptor Region */
if (!((read32((void *)(desc + FLMSTR1)) >> FLMSTR_WR_SHIFT_V2) & BIT(0))) {
printk(BIOS_ERR, "Host doesn't have write access to Descriptor Region\n");
return 0;
}
return 1;
}
void configure_descriptor(struct descriptor_byte *bytes, size_t num)
{
uint8_t si_desc_buf[CONFIG_SI_DESC_REGION_SZ];
struct region_device desc_rdev;
bool update_required = false;
if (fmap_locate_area_as_rdev_rw(CONFIG_SI_DESC_REGION, &desc_rdev) < 0) {
printk(BIOS_ERR, "Failed to locate %s in the FMAP\n", CONFIG_SI_DESC_REGION);
return;
}
if (rdev_readat(&desc_rdev, si_desc_buf, 0, CONFIG_SI_DESC_REGION_SZ) !=
CONFIG_SI_DESC_REGION_SZ) {
printk(BIOS_ERR, "Failed to read Descriptor Region from SPI Flash\n");
return;
}
if (!is_descriptor_writeable(si_desc_buf))
return;
for (size_t i = 0; i < num; i++) {
size_t offset = bytes[i].offset;
uint8_t desired_value = bytes[i].desired_value;
printk(BIOS_DEBUG, "Current value of Descriptor byte 0x%lx: 0x%x\n",
offset, si_desc_buf[offset]);
if (si_desc_buf[offset] != desired_value) {
update_required = true;
si_desc_buf[offset] = desired_value;
}
}
if (!update_required) {
printk(BIOS_DEBUG, "Update of Descriptor is not required!\n");
return;
}
if (rdev_eraseat(&desc_rdev, 0, CONFIG_SI_DESC_REGION_SZ) != CONFIG_SI_DESC_REGION_SZ) {
printk(BIOS_ERR, "Failed to erase Descriptor Region area\n");
return;
}
if (rdev_writeat(&desc_rdev, si_desc_buf, 0, CONFIG_SI_DESC_REGION_SZ)
!= CONFIG_SI_DESC_REGION_SZ) {
printk(BIOS_ERR, "Failed to update Descriptor Region\n");
return;
}
printk(BIOS_DEBUG, "Update of Descriptor successful, trigger GLOBAL RESET\n");
pmc_global_reset_enable(true);
do_full_reset();
die("Failed to trigger GLOBAL RESET\n");
}

View File

@ -9,6 +9,11 @@
#error "Please select exactly one PCH type"
#endif
struct descriptor_byte {
size_t offset;
uint8_t desired_value;
};
/* Bootblock pre console init programming */
void bootblock_pch_early_init(void);
@ -17,4 +22,6 @@ void bootblock_pch_init(void);
void pch_early_iorange_init(void);
void report_platform_info(void);
void configure_descriptor(struct descriptor_byte *bytes, size_t num);
#endif